LLVM 24.0.0git
AArch64InstrInfo.cpp
Go to the documentation of this file.
1//===- AArch64InstrInfo.cpp - AArch64 Instruction Information -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the AArch64 implementation of the TargetInstrInfo class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "AArch64InstrInfo.h"
14#include "AArch64ExpandImm.h"
16#include "AArch64PointerAuth.h"
17#include "AArch64Subtarget.h"
22#include "llvm/ADT/ArrayRef.h"
23#include "llvm/ADT/STLExtras.h"
24#include "llvm/ADT/SmallSet.h"
26#include "llvm/ADT/Statistic.h"
45#include "llvm/IR/DebugLoc.h"
46#include "llvm/IR/GlobalValue.h"
47#include "llvm/IR/Module.h"
48#include "llvm/MC/MCAsmInfo.h"
49#include "llvm/MC/MCInst.h"
51#include "llvm/MC/MCInstrDesc.h"
56#include "llvm/Support/LEB128.h"
60#include <cassert>
61#include <cstdint>
62#include <iterator>
63#include <utility>
64
65using namespace llvm;
66
67#define GET_INSTRINFO_CTOR_DTOR
68#include "AArch64GenInstrInfo.inc"
69
70#define DEBUG_TYPE "AArch64InstrInfo"
71
72STATISTIC(NumCopyInstrs, "Number of COPY instructions expanded");
73STATISTIC(NumZCRegMoveInstrsGPR, "Number of zero-cycle GPR register move "
74 "instructions expanded from canonical COPY");
75STATISTIC(NumZCRegMoveInstrsFPR, "Number of zero-cycle FPR register move "
76 "instructions expanded from canonical COPY");
77STATISTIC(NumZCZeroingInstrsGPR, "Number of zero-cycle GPR zeroing "
78 "instructions expanded from canonical COPY");
79// NumZCZeroingInstrsFPR is counted at AArch64AsmPrinter
80
82 CBDisplacementBits("aarch64-cb-offset-bits", cl::Hidden, cl::init(9),
83 cl::desc("Restrict range of CB instructions (DEBUG)"));
84
86 "aarch64-tbz-offset-bits", cl::Hidden, cl::init(14),
87 cl::desc("Restrict range of TB[N]Z instructions (DEBUG)"));
88
90 "aarch64-cbz-offset-bits", cl::Hidden, cl::init(19),
91 cl::desc("Restrict range of CB[N]Z instructions (DEBUG)"));
92
94 BCCDisplacementBits("aarch64-bcc-offset-bits", cl::Hidden, cl::init(19),
95 cl::desc("Restrict range of Bcc instructions (DEBUG)"));
96
98 BDisplacementBits("aarch64-b-offset-bits", cl::Hidden, cl::init(26),
99 cl::desc("Restrict range of B instructions (DEBUG)"));
100
102 "aarch64-search-limit", cl::Hidden, cl::init(2048),
103 cl::desc("Restrict range of instructions to search for the "
104 "machine-combiner gather pattern optimization"));
105
107 "aarch64-outliner-compact-unwind-frame", cl::Hidden, cl::init(true),
108 cl::desc("Use a frame record for Mach-O non-leaf outlined functions"));
109
111 : AArch64GenInstrInfo(STI, RI, AArch64::ADJCALLSTACKDOWN,
112 AArch64::ADJCALLSTACKUP, AArch64::CATCHRET),
113 RI(STI.getTargetTriple(), STI.getHwMode()), Subtarget(STI) {}
114
115/// Return the maximum number of bytes of code the specified instruction may be
116/// after LFI rewriting. If the instruction is not rewritten, std::nullopt is
117/// returned (use default sizing).
118///
119/// NOTE: the size estimates here must be kept in sync with the rewrites in
120/// AArch64MCLFIRewriter.cpp. Sizes may be overestimates of the rewritten
121/// instruction sequences.
122static std::optional<unsigned> getLFIInstSizeInBytes(const MachineInstr &MI) {
123 switch (MI.getOpcode()) {
124 case AArch64::SVC:
125 // SVC expands to 4 instructions.
126 return 16;
127 case AArch64::BR:
128 case AArch64::BLR:
129 // Indirect branches/calls expand to 2 instructions (guard + br/blr).
130 return 8;
131 case AArch64::RET:
132 // RET through another register expands to 2 instructions (guard + ret).
133 // RET through LR may also expand to 2 instructions if a deferred LR guard
134 // is flushed before the return.
135 return 8;
136 case AArch64::RETAA:
137 case AArch64::RETAB:
138 // Authenticated returns expand to 3 instructions (authenticate + guard +
139 // ret).
140 return 12;
141 case AArch64::BRAA:
142 case AArch64::BRAAZ:
143 case AArch64::BRAB:
144 case AArch64::BRABZ:
145 case AArch64::BLRAA:
146 case AArch64::BLRAAZ:
147 case AArch64::BLRAB:
148 case AArch64::BLRABZ:
149 // Authenticated branches/calls expand to 3 instructions (authenticate +
150 // guard + branch).
151 return 12;
152 case AArch64::AUTIASP:
153 case AArch64::AUTIBSP:
154 case AArch64::AUTIAZ:
155 case AArch64::AUTIBZ:
156 case AArch64::XPACLRI:
157 // Authenticating LR expands to the instruction plus a deferred LR guard.
158 return 8;
159 case AArch64::SYSxt:
160 // VA-based DC/IC ops (op1=3, Cn=7, op2=1) expand to 2 instructions.
161 if (MI.getOperand(0).getImm() == 3 && MI.getOperand(1).getImm() == 7 &&
162 MI.getOperand(3).getImm() == 1)
163 return 8;
164 return std::nullopt;
165 default:
166 break;
167 }
168
169 // Detect instructions that explicitly define SP or LR.
170 bool ModifiesLR = false;
171 bool ModifiesSP = false;
172 for (const MachineOperand &MO : MI.defs()) {
173 if (!MO.isReg())
174 continue;
175 if (MO.getReg() == AArch64::LR)
176 ModifiesLR = true;
177 else if (MO.getReg() == AArch64::SP)
178 ModifiesSP = true;
179 }
180
181 // Memory accesses expand to a base-register guard plus the rewritten access
182 // (8 bytes), with an extra base-register update for pre/post-index forms (12
183 // bytes total). If the access also defines LR, an LR mask is appended (+4
184 // bytes). Depending on additional optimizations that the rewriter performs,
185 // this may be an overestimate.
186 if (MI.mayLoadOrStore()) {
187 unsigned Size = isLFIPrePostMemAccess(MI.getOpcode()) ? 12 : 8;
188 if (ModifiesLR)
189 Size += 4;
190 return Size;
191 }
192
193 // Non memory operations that modify LR or SP expand to 2 instructions.
194 if (ModifiesSP || ModifiesLR)
195 return 8;
196
197 // Default case: instructions that don't cause expansion.
198 // - TP accesses in LFI are a single load/store, so no expansion.
199 // - All remaining instructions are not rewritten.
200 return std::nullopt;
201}
202
203/// GetInstSize - Return the number of bytes of code the specified
204/// instruction may be. This returns the maximum number of bytes.
206 const MCInstrDesc &Desc = MI.getDesc();
207 if (!Desc.isPseudo() && !Subtarget.isLFI()) {
208 assert(Desc.getSize() == 4 && "Unexpected instruction size");
209 return 4;
210 }
211
212 const MachineBasicBlock &MBB = *MI.getParent();
213 const MachineFunction *MF = MBB.getParent();
214 const Function &F = MF->getFunction();
215 const MCAsmInfo &MAI = MF->getTarget().getMCAsmInfo();
216
217 {
218 auto Op = MI.getOpcode();
219 if (Op == AArch64::INLINEASM || Op == AArch64::INLINEASM_BR)
220 return getInlineAsmLength(MI.getOperand(0).getSymbolName(), MAI);
221 }
222
223 // Meta-instructions emit no code.
224 if (MI.isMetaInstruction())
225 return 0;
226
227 // FIXME: We currently only handle pseudoinstructions that don't get expanded
228 // before the assembly printer.
229 unsigned NumBytes = 0;
230
231 // LFI rewriter expansions that supersede normal sizing.
232 const auto &STI = MF->getSubtarget<AArch64Subtarget>();
233 if (STI.isLFI())
234 if (auto Size = getLFIInstSizeInBytes(MI))
235 return *Size;
236
237 if (!MI.isBundle() && isTailCallReturnInst(MI)) {
238 NumBytes = Desc.getSize() ? Desc.getSize() : 4;
239
240 const auto *MFI = MF->getInfo<AArch64FunctionInfo>();
241 if (!MFI->shouldSignReturnAddress(*MF))
242 return NumBytes;
243
244 auto Method = STI.getAuthenticatedLRCheckMethod(*MF);
245 NumBytes += AArch64PAuth::getCheckerSizeInBytes(Method);
246 return NumBytes;
247 }
248
249 // Size should be preferably set in
250 // llvm/lib/Target/AArch64/AArch64InstrInfo.td (default case).
251 // Specific cases handle instructions of variable sizes
252 switch (Desc.getOpcode()) {
253 default:
254 if (Desc.getSize())
255 return Desc.getSize();
256
257 // Anything not explicitly designated otherwise (i.e. pseudo-instructions
258 // with fixed constant size but not specified in .td file) is a normal
259 // 4-byte insn.
260 NumBytes = 4;
261 break;
262 case TargetOpcode::STACKMAP:
263 // The upper bound for a stackmap intrinsic is the full length of its shadow
264 NumBytes = StackMapOpers(&MI).getNumPatchBytes();
265 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
266 break;
267 case TargetOpcode::PATCHPOINT:
268 // The size of the patchpoint intrinsic is the number of bytes requested
269 NumBytes = PatchPointOpers(&MI).getNumPatchBytes();
270 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
271 break;
272 case TargetOpcode::STATEPOINT:
273 NumBytes = StatepointOpers(&MI).getNumPatchBytes();
274 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
275 // No patch bytes means a normal call inst is emitted
276 if (NumBytes == 0)
277 NumBytes = 4;
278 break;
279 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
280 // If `patchable-function-entry` is set, PATCHABLE_FUNCTION_ENTER
281 // instructions are expanded to the specified number of NOPs. Otherwise,
282 // they are expanded to 36-byte XRay sleds.
283 NumBytes =
284 F.getFnAttributeAsParsedInteger("patchable-function-entry", 9) * 4;
285 break;
286 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
287 case TargetOpcode::PATCHABLE_TAIL_CALL:
288 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
289 // An XRay sled can be 4 bytes of alignment plus a 32-byte block.
290 NumBytes = 36;
291 break;
292 case TargetOpcode::PATCHABLE_EVENT_CALL:
293 // EVENT_CALL XRay sleds are exactly 6 instructions long (no alignment).
294 NumBytes = 24;
295 break;
296
297 case AArch64::SPACE:
298 NumBytes = MI.getOperand(1).getImm();
299 break;
300 case AArch64::MOVaddr:
301 case AArch64::MOVaddrJT:
302 case AArch64::MOVaddrCP:
303 case AArch64::MOVaddrBA:
304 case AArch64::MOVaddrTLS:
305 case AArch64::MOVaddrEXT: {
306 // Use the same logic as the pseudo expansion to count instructions.
309 MI.getOperand(1).getTargetFlags(),
310 Subtarget.isTargetMachO(), Insn);
311 NumBytes = Insn.size() * 4;
312 break;
313 }
314
315 case AArch64::MOVi32imm:
316 case AArch64::MOVi64imm: {
317 // Use the same logic as the pseudo expansion to count instructions.
318 unsigned BitSize = Desc.getOpcode() == AArch64::MOVi32imm ? 32 : 64;
320 AArch64_IMM::expandMOVImm(MI.getOperand(1).getImm(), BitSize, Insn);
321 NumBytes = Insn.size() * 4;
322 break;
323 }
324
325 case TargetOpcode::BUNDLE:
326 NumBytes = getInstBundleSize(MI);
327 break;
328 }
329
330 return NumBytes;
331}
332
335 // Block ends with fall-through condbranch.
336 switch (LastInst->getOpcode()) {
337 default:
338 llvm_unreachable("Unknown branch instruction?");
339 case AArch64::Bcc:
340 Target = LastInst->getOperand(1).getMBB();
341 Cond.push_back(LastInst->getOperand(0));
342 break;
343 case AArch64::CBZW:
344 case AArch64::CBZX:
345 case AArch64::CBNZW:
346 case AArch64::CBNZX:
347 Target = LastInst->getOperand(1).getMBB();
348 Cond.push_back(MachineOperand::CreateImm(-1));
349 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
350 Cond.push_back(LastInst->getOperand(0));
351 break;
352 case AArch64::TBZW:
353 case AArch64::TBZX:
354 case AArch64::TBNZW:
355 case AArch64::TBNZX:
356 Target = LastInst->getOperand(2).getMBB();
357 Cond.push_back(MachineOperand::CreateImm(-1));
358 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
359 Cond.push_back(LastInst->getOperand(0));
360 Cond.push_back(LastInst->getOperand(1));
361 break;
362 case AArch64::CBWPri:
363 case AArch64::CBXPri:
364 case AArch64::CBWPrr:
365 case AArch64::CBXPrr:
366 Target = LastInst->getOperand(3).getMBB();
367 Cond.push_back(MachineOperand::CreateImm(-1));
368 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
369 Cond.push_back(LastInst->getOperand(0));
370 Cond.push_back(LastInst->getOperand(1));
371 Cond.push_back(LastInst->getOperand(2));
372 break;
373 case AArch64::CBBAssertExt:
374 case AArch64::CBHAssertExt:
375 Target = LastInst->getOperand(3).getMBB();
376 Cond.push_back(MachineOperand::CreateImm(-1)); // -1
377 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); // Opc
378 Cond.push_back(LastInst->getOperand(0)); // Cond
379 Cond.push_back(LastInst->getOperand(1)); // Op0
380 Cond.push_back(LastInst->getOperand(2)); // Op1
381 Cond.push_back(LastInst->getOperand(4)); // Ext0
382 Cond.push_back(LastInst->getOperand(5)); // Ext1
383 break;
384 }
385}
386
387static unsigned getBranchDisplacementBits(unsigned Opc) {
388 switch (Opc) {
389 default:
390 llvm_unreachable("unexpected opcode!");
391 case AArch64::B:
392 return BDisplacementBits;
393 case AArch64::TBNZW:
394 case AArch64::TBZW:
395 case AArch64::TBNZX:
396 case AArch64::TBZX:
397 return TBZDisplacementBits;
398 case AArch64::CBNZW:
399 case AArch64::CBZW:
400 case AArch64::CBNZX:
401 case AArch64::CBZX:
402 return CBZDisplacementBits;
403 case AArch64::Bcc:
404 return BCCDisplacementBits;
405 case AArch64::CBWPri:
406 case AArch64::CBXPri:
407 case AArch64::CBBAssertExt:
408 case AArch64::CBHAssertExt:
409 case AArch64::CBWPrr:
410 case AArch64::CBXPrr:
411 return CBDisplacementBits;
412 }
413}
414
416 int64_t BrOffset) const {
417 unsigned Bits = getBranchDisplacementBits(BranchOp);
418 assert(Bits >= 3 && "max branch displacement must be enough to jump"
419 "over conditional branch expansion");
420 return isIntN(Bits, BrOffset / 4);
421}
422
425 switch (MI.getOpcode()) {
426 default:
427 llvm_unreachable("unexpected opcode!");
428 case AArch64::B:
429 return MI.getOperand(0).getMBB();
430 case AArch64::TBZW:
431 case AArch64::TBNZW:
432 case AArch64::TBZX:
433 case AArch64::TBNZX:
434 return MI.getOperand(2).getMBB();
435 case AArch64::CBZW:
436 case AArch64::CBNZW:
437 case AArch64::CBZX:
438 case AArch64::CBNZX:
439 case AArch64::Bcc:
440 return MI.getOperand(1).getMBB();
441 case AArch64::CBWPri:
442 case AArch64::CBXPri:
443 case AArch64::CBBAssertExt:
444 case AArch64::CBHAssertExt:
445 case AArch64::CBWPrr:
446 case AArch64::CBXPrr:
447 return MI.getOperand(3).getMBB();
448 }
449}
450
452 MachineBasicBlock &NewDestBB,
453 MachineBasicBlock &RestoreBB,
454 const DebugLoc &DL,
455 int64_t BrOffset,
456 RegScavenger *RS) const {
457 assert(RS && "RegScavenger required for long branching");
458 assert(MBB.empty() &&
459 "new block should be inserted for expanding unconditional branch");
460 assert(MBB.pred_size() == 1);
461 assert(RestoreBB.empty() &&
462 "restore block should be inserted for restoring clobbered registers");
463
464 auto buildIndirectBranch = [&](Register Reg, MachineBasicBlock &DestBB) {
465 // Offsets outside of the signed 33-bit range are not supported for ADRP +
466 // ADD.
467 if (!isInt<33>(BrOffset))
469 "Branch offsets outside of the signed 33-bit range not supported");
470
471 BuildMI(MBB, MBB.end(), DL, get(AArch64::ADRP), Reg)
472 .addSym(DestBB.getSymbol(), AArch64II::MO_PAGE);
473 BuildMI(MBB, MBB.end(), DL, get(AArch64::ADDXri), Reg)
474 .addReg(Reg)
475 .addSym(DestBB.getSymbol(), AArch64II::MO_PAGEOFF | AArch64II::MO_NC)
476 .addImm(0);
477 BuildMI(MBB, MBB.end(), DL, get(AArch64::BR)).addReg(Reg);
478 };
479
480 RS->enterBasicBlockEnd(MBB);
481 // If X16 is unused, we can rely on the linker to insert a range extension
482 // thunk if NewDestBB is out of range of a single B instruction.
483 constexpr Register Reg = AArch64::X16;
484 if (!RS->isRegUsed(Reg)) {
485 insertUnconditionalBranch(MBB, &NewDestBB, DL);
486 RS->setRegUsed(Reg);
487 return;
488 }
489
490 // In a cold block without BTI, insert the indirect branch if a register is
491 // free. Skip this if BTI is enabled to avoid inserting a BTI at the target,
492 // prioritizing a dynamic cost in cold code over a static cost in hot code.
493 AArch64FunctionInfo *AFI = MBB.getParent()->getInfo<AArch64FunctionInfo>();
494 bool HasBTI = AFI && AFI->branchTargetEnforcement();
495 if (MBB.getSectionID() == MBBSectionID::ColdSectionID && !HasBTI) {
496 Register Scavenged = RS->FindUnusedReg(&AArch64::GPR64RegClass);
497 if (Scavenged.isValid()) {
498 buildIndirectBranch(Scavenged, NewDestBB);
499 RS->setRegUsed(Scavenged);
500 return;
501 }
502 }
503
504 // Note: Spilling X16 briefly moves the stack pointer, making it incompatible
505 // with red zones.
506 if (!AFI || AFI->hasRedZone().value_or(true))
508 "Unable to insert indirect branch inside function that has red zone");
509
510 // Otherwise, spill X16 and defer range extension to the linker.
511 BuildMI(MBB, MBB.end(), DL, get(AArch64::STRXpre))
512 .addReg(AArch64::SP, RegState::Define)
513 .addReg(Reg)
514 .addReg(AArch64::SP)
515 .addImm(-16);
516
517 BuildMI(MBB, MBB.end(), DL, get(AArch64::B)).addMBB(&RestoreBB);
518
519 BuildMI(RestoreBB, RestoreBB.end(), DL, get(AArch64::LDRXpost))
520 .addReg(AArch64::SP, RegState::Define)
522 .addReg(AArch64::SP)
523 .addImm(16);
524}
525
526// Branch analysis.
529 MachineBasicBlock *&FBB,
531 bool AllowModify) const {
532 // If the block has no terminators, it just falls into the block after it.
533 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
534 if (I == MBB.end())
535 return false;
536
537 // Skip over SpeculationBarrierEndBB terminators
538 if (I->getOpcode() == AArch64::SpeculationBarrierISBDSBEndBB ||
539 I->getOpcode() == AArch64::SpeculationBarrierSBEndBB) {
540 --I;
541 }
542
543 if (!isUnpredicatedTerminator(*I))
544 return false;
545
546 // Get the last instruction in the block.
547 MachineInstr *LastInst = &*I;
548
549 // If there is only one terminator instruction, process it.
550 unsigned LastOpc = LastInst->getOpcode();
551 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
552 if (isUncondBranchOpcode(LastOpc)) {
553 TBB = LastInst->getOperand(0).getMBB();
554 return false;
555 }
556 if (isCondBranchOpcode(LastOpc)) {
557 // Block ends with fall-through condbranch.
558 parseCondBranch(LastInst, TBB, Cond);
559 return false;
560 }
561 return true; // Can't handle indirect branch.
562 }
563
564 // Get the instruction before it if it is a terminator.
565 MachineInstr *SecondLastInst = &*I;
566 unsigned SecondLastOpc = SecondLastInst->getOpcode();
567
568 // If AllowModify is true and the block ends with two or more unconditional
569 // branches, delete all but the first unconditional branch.
570 if (AllowModify && isUncondBranchOpcode(LastOpc)) {
571 while (isUncondBranchOpcode(SecondLastOpc)) {
572 LastInst->eraseFromParent();
573 LastInst = SecondLastInst;
574 LastOpc = LastInst->getOpcode();
575 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
576 // Return now the only terminator is an unconditional branch.
577 TBB = LastInst->getOperand(0).getMBB();
578 return false;
579 }
580 SecondLastInst = &*I;
581 SecondLastOpc = SecondLastInst->getOpcode();
582 }
583 }
584
585 // If we're allowed to modify and the block ends in a unconditional branch
586 // which could simply fallthrough, remove the branch. (Note: This case only
587 // matters when we can't understand the whole sequence, otherwise it's also
588 // handled by BranchFolding.cpp.)
589 if (AllowModify && isUncondBranchOpcode(LastOpc) &&
590 MBB.isLayoutSuccessor(getBranchDestBlock(*LastInst))) {
591 LastInst->eraseFromParent();
592 LastInst = SecondLastInst;
593 LastOpc = LastInst->getOpcode();
594 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
595 assert(!isUncondBranchOpcode(LastOpc) &&
596 "unreachable unconditional branches removed above");
597
598 if (isCondBranchOpcode(LastOpc)) {
599 // Block ends with fall-through condbranch.
600 parseCondBranch(LastInst, TBB, Cond);
601 return false;
602 }
603 return true; // Can't handle indirect branch.
604 }
605 SecondLastInst = &*I;
606 SecondLastOpc = SecondLastInst->getOpcode();
607 }
608
609 // If there are three terminators, we don't know what sort of block this is.
610 if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))
611 return true;
612
613 // If the block ends with a B and a Bcc, handle it.
614 if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
615 parseCondBranch(SecondLastInst, TBB, Cond);
616 FBB = LastInst->getOperand(0).getMBB();
617 return false;
618 }
619
620 // If the block ends with two unconditional branches, handle it. The second
621 // one is not executed, so remove it.
622 if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
623 TBB = SecondLastInst->getOperand(0).getMBB();
624 I = LastInst;
625 if (AllowModify)
626 I->eraseFromParent();
627 return false;
628 }
629
630 // ...likewise if it ends with an indirect branch followed by an unconditional
631 // branch.
632 if (isIndirectBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
633 I = LastInst;
634 if (AllowModify)
635 I->eraseFromParent();
636 return true;
637 }
638
639 // Otherwise, can't handle this.
640 return true;
641}
642
644 MachineBranchPredicate &MBP,
645 bool AllowModify) const {
646 // Use analyzeBranch to validate the branch pattern.
647 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
649 if (analyzeBranch(MBB, TBB, FBB, Cond, AllowModify))
650 return true;
651
652 // analyzeBranch returns success with empty Cond for unconditional branches.
653 if (Cond.empty())
654 return true;
655
656 MBP.TrueDest = TBB;
657 assert(MBP.TrueDest && "expected!");
658 MBP.FalseDest = FBB ? FBB : MBB.getNextNode();
659
660 MBP.ConditionDef = nullptr;
661 MBP.SingleUseCondition = false;
662
663 // Find the conditional branch. After analyzeBranch succeeds with non-empty
664 // Cond, there's exactly one conditional branch - either last (fallthrough)
665 // or second-to-last (followed by unconditional B).
666 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
667 if (I == MBB.end())
668 return true;
669
670 if (isUncondBranchOpcode(I->getOpcode())) {
671 if (I == MBB.begin())
672 return true;
673 --I;
674 }
675
676 MachineInstr *CondBranch = &*I;
677 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
678
679 switch (CondBranch->getOpcode()) {
680 default:
681 return true;
682
683 case AArch64::Bcc:
684 // Bcc takes the NZCV flag as the operand to branch on, walk up the
685 // instruction stream to find the last instruction to define NZCV.
687 if (MI.modifiesRegister(AArch64::NZCV, /*TRI=*/nullptr)) {
688 MBP.ConditionDef = &MI;
689 break;
690 }
691 }
692 return false;
693
694 case AArch64::CBZW:
695 case AArch64::CBZX:
696 case AArch64::CBNZW:
697 case AArch64::CBNZX: {
698 MBP.LHS = CondBranch->getOperand(0);
699 MBP.RHS = MachineOperand::CreateImm(0);
700 unsigned Opc = CondBranch->getOpcode();
701 MBP.Predicate = (Opc == AArch64::CBNZX || Opc == AArch64::CBNZW)
702 ? MachineBranchPredicate::PRED_NE
703 : MachineBranchPredicate::PRED_EQ;
704 Register CondReg = MBP.LHS.getReg();
705 if (CondReg.isVirtual())
706 MBP.ConditionDef = MRI.getVRegDef(CondReg);
707 return false;
708 }
709
710 case AArch64::TBZW:
711 case AArch64::TBZX:
712 case AArch64::TBNZW:
713 case AArch64::TBNZX: {
714 Register CondReg = CondBranch->getOperand(0).getReg();
715 if (CondReg.isVirtual())
716 MBP.ConditionDef = MRI.getVRegDef(CondReg);
717 return false;
718 }
719 }
720}
721
724 if (Cond[0].getImm() != -1) {
725 // Regular Bcc
726 AArch64CC::CondCode CC = (AArch64CC::CondCode)(int)Cond[0].getImm();
728 } else {
729 // Folded compare-and-branch
730 switch (Cond[1].getImm()) {
731 default:
732 llvm_unreachable("Unknown conditional branch!");
733 case AArch64::CBZW:
734 Cond[1].setImm(AArch64::CBNZW);
735 break;
736 case AArch64::CBNZW:
737 Cond[1].setImm(AArch64::CBZW);
738 break;
739 case AArch64::CBZX:
740 Cond[1].setImm(AArch64::CBNZX);
741 break;
742 case AArch64::CBNZX:
743 Cond[1].setImm(AArch64::CBZX);
744 break;
745 case AArch64::TBZW:
746 Cond[1].setImm(AArch64::TBNZW);
747 break;
748 case AArch64::TBNZW:
749 Cond[1].setImm(AArch64::TBZW);
750 break;
751 case AArch64::TBZX:
752 Cond[1].setImm(AArch64::TBNZX);
753 break;
754 case AArch64::TBNZX:
755 Cond[1].setImm(AArch64::TBZX);
756 break;
757
758 // Cond is { -1, Opcode, CC, Op0, Op1, ... }
759 case AArch64::CBWPri:
760 case AArch64::CBXPri:
761 case AArch64::CBBAssertExt:
762 case AArch64::CBHAssertExt:
763 case AArch64::CBWPrr:
764 case AArch64::CBXPrr: {
765 // Pseudos using standard 4bit Arm condition codes
767 static_cast<AArch64CC::CondCode>(Cond[2].getImm());
769 }
770 }
771 }
772
773 return false;
774}
775
777 int *BytesRemoved) const {
778 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
779 if (I == MBB.end())
780 return 0;
781
782 if (!isUncondBranchOpcode(I->getOpcode()) &&
783 !isCondBranchOpcode(I->getOpcode()))
784 return 0;
785
786 // Remove the branch.
787 I->eraseFromParent();
788
789 I = MBB.end();
790
791 if (I == MBB.begin()) {
792 if (BytesRemoved)
793 *BytesRemoved = 4;
794 return 1;
795 }
796 --I;
797 if (!isCondBranchOpcode(I->getOpcode())) {
798 if (BytesRemoved)
799 *BytesRemoved = 4;
800 return 1;
801 }
802
803 // Remove the branch.
804 I->eraseFromParent();
805 if (BytesRemoved)
806 *BytesRemoved = 8;
807
808 return 2;
809}
810
811void AArch64InstrInfo::instantiateCondBranch(
814 if (Cond[0].getImm() != -1) {
815 // Regular Bcc
816 BuildMI(&MBB, DL, get(AArch64::Bcc)).addImm(Cond[0].getImm()).addMBB(TBB);
817 } else {
818 // Folded compare-and-branch
819 // Note that we use addOperand instead of addReg to keep the flags.
820
821 // cbz, cbnz
822 const MachineInstrBuilder MIB =
823 BuildMI(&MBB, DL, get(Cond[1].getImm())).add(Cond[2]);
824
825 // tbz/tbnz
826 if (Cond.size() > 3)
827 MIB.add(Cond[3]);
828
829 // cb
830 if (Cond.size() > 4)
831 MIB.add(Cond[4]);
832
833 MIB.addMBB(TBB);
834
835 // cb[b,h]
836 if (Cond.size() > 5) {
837 MIB.addImm(Cond[5].getImm());
838 MIB.addImm(Cond[6].getImm());
839 }
840 }
841}
842
845 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
846 // Shouldn't be a fall through.
847 assert(TBB && "insertBranch must not be told to insert a fallthrough");
848
849 if (!FBB) {
850 if (Cond.empty()) // Unconditional branch?
851 BuildMI(&MBB, DL, get(AArch64::B)).addMBB(TBB);
852 else
853 instantiateCondBranch(MBB, DL, TBB, Cond);
854
855 if (BytesAdded)
856 *BytesAdded = 4;
857
858 return 1;
859 }
860
861 // Two-way conditional branch.
862 instantiateCondBranch(MBB, DL, TBB, Cond);
863 BuildMI(&MBB, DL, get(AArch64::B)).addMBB(FBB);
864
865 if (BytesAdded)
866 *BytesAdded = 8;
867
868 return 2;
869}
870
871#ifndef NDEBUG
873 switch (Ext) {
874 default:
875 return false;
876 case AArch64_AM::UXTB:
877 case AArch64_AM::SXTB:
878 return Opc == AArch64::CBBAssertExt;
879 case AArch64_AM::UXTH:
880 case AArch64_AM::SXTH:
881 return Opc == AArch64::CBHAssertExt;
882 }
883}
884#endif
885
889 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
890
891 // Parse the condition code, see parseCondBranch() above.
893 switch (Cond.size()) {
894 default:
895 llvm_unreachable("Unknown condition opcode in Cond");
896 case 1: // b.cc
898 break;
899 case 3: { // cbz/cbnz
900 // We must insert a compare against 0.
901 bool Is64Bit;
902 switch (Cond[1].getImm()) {
903 default:
904 llvm_unreachable("Unknown branch opcode in Cond");
905 case AArch64::CBZW:
906 Is64Bit = false;
907 CC = AArch64CC::EQ;
908 break;
909 case AArch64::CBZX:
910 Is64Bit = true;
911 CC = AArch64CC::EQ;
912 break;
913 case AArch64::CBNZW:
914 Is64Bit = false;
915 CC = AArch64CC::NE;
916 break;
917 case AArch64::CBNZX:
918 Is64Bit = true;
919 CC = AArch64CC::NE;
920 break;
921 }
922 Register SrcReg = Cond[2].getReg();
923 if (Is64Bit) {
924 // cmp reg, #0 is actually subs xzr, reg, #0.
925 MRI.constrainRegClass(SrcReg, &AArch64::GPR64spRegClass);
926 BuildMI(MBB, MI, DL, get(AArch64::SUBSXri), AArch64::XZR)
927 .addReg(SrcReg)
928 .addImm(0)
929 .addImm(0);
930 } else {
931 MRI.constrainRegClass(SrcReg, &AArch64::GPR32spRegClass);
932 BuildMI(MBB, MI, DL, get(AArch64::SUBSWri), AArch64::WZR)
933 .addReg(SrcReg)
934 .addImm(0)
935 .addImm(0);
936 }
937 } break;
938 case 4: { // tbz/tbnz
939 // We must insert a tst instruction.
940 switch (Cond[1].getImm()) {
941 default:
942 llvm_unreachable("Unknown branch opcode in Cond");
943 case AArch64::TBZW:
944 case AArch64::TBZX:
945 CC = AArch64CC::EQ;
946 break;
947 case AArch64::TBNZW:
948 case AArch64::TBNZX:
949 CC = AArch64CC::NE;
950 break;
951 }
952 // cmp reg, #foo is actually ands xzr, reg, #1<<foo.
953 if (Cond[1].getImm() == AArch64::TBZW || Cond[1].getImm() == AArch64::TBNZW)
954 BuildMI(MBB, MI, DL, get(AArch64::ANDSWri), AArch64::WZR)
955 .addReg(Cond[2].getReg())
956 .addImm(
958 else
959 BuildMI(MBB, MI, DL, get(AArch64::ANDSXri), AArch64::XZR)
960 .addReg(Cond[2].getReg())
961 .addImm(
963 } break;
964 case 5: { // cb
965 // We must insert a cmp, that is a subs
966 // 0 1 2 3 4
967 // Cond is { -1, Opcode, CC, Op0, Op1 }
968 unsigned SubsOpc, SubsDestReg;
969 bool IsImm = false;
970 CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
971 switch (Cond[1].getImm()) {
972 default:
973 llvm_unreachable("Unknown branch opcode in Cond");
974 case AArch64::CBWPri:
975 SubsOpc = AArch64::SUBSWri;
976 SubsDestReg = AArch64::WZR;
977 IsImm = true;
978 break;
979 case AArch64::CBXPri:
980 SubsOpc = AArch64::SUBSXri;
981 SubsDestReg = AArch64::XZR;
982 IsImm = true;
983 break;
984 case AArch64::CBWPrr:
985 SubsOpc = AArch64::SUBSWrr;
986 SubsDestReg = AArch64::WZR;
987 IsImm = false;
988 break;
989 case AArch64::CBXPrr:
990 SubsOpc = AArch64::SUBSXrr;
991 SubsDestReg = AArch64::XZR;
992 IsImm = false;
993 break;
994 }
995
996 if (IsImm) {
997 MRI.constrainRegClass(Cond[3].getReg(), getRegClass(get(SubsOpc), 1));
998 BuildMI(MBB, MI, DL, get(SubsOpc), SubsDestReg)
999 .addReg(Cond[3].getReg())
1000 .addImm(Cond[4].getImm())
1001 .addImm(0);
1002 } else {
1003 MRI.constrainRegClass(Cond[3].getReg(), getRegClass(get(SubsOpc), 1));
1004 MRI.constrainRegClass(Cond[4].getReg(), getRegClass(get(SubsOpc), 2));
1005 BuildMI(MBB, MI, DL, get(SubsOpc), SubsDestReg)
1006 .addReg(Cond[3].getReg())
1007 .addReg(Cond[4].getReg());
1008 }
1009 } break;
1010 case 7: { // cb[b,h]
1011 // We must insert a cmp, that is a subs, but also zero- or sign-extensions
1012 // that have been folded. For the first operand we codegen an explicit
1013 // extension, for the second operand we fold the extension into cmp.
1014 // 0 1 2 3 4 5 6
1015 // Cond is { -1, Opcode, CC, Op0, Op1, Ext0, Ext1 }
1016
1017 // We need a new register for the now explicitly extended register
1018 Register Reg = Cond[3].getReg();
1020 unsigned ExtOpc;
1021 unsigned ExtBits;
1022 AArch64_AM::ShiftExtendType ExtendType =
1024 assert(isValidCBExtend(Cond[1].getImm(), ExtendType) &&
1025 "Unexpected compare-and-branch instruction for extend type");
1026 switch (ExtendType) {
1027 default:
1028 llvm_unreachable("Unknown shift-extend for CB instruction");
1029 case AArch64_AM::SXTB:
1030 ExtOpc = AArch64::SBFMWri;
1031 ExtBits = AArch64_AM::encodeLogicalImmediate(0xff, 32);
1032 break;
1033 case AArch64_AM::SXTH:
1034 ExtOpc = AArch64::SBFMWri;
1035 ExtBits = AArch64_AM::encodeLogicalImmediate(0xffff, 32);
1036 break;
1037 case AArch64_AM::UXTB:
1038 ExtOpc = AArch64::ANDWri;
1039 ExtBits = AArch64_AM::encodeLogicalImmediate(0xff, 32);
1040 break;
1041 case AArch64_AM::UXTH:
1042 ExtOpc = AArch64::ANDWri;
1043 ExtBits = AArch64_AM::encodeLogicalImmediate(0xffff, 32);
1044 break;
1045 }
1046
1047 // Build the explicit extension of the first operand
1048 Reg = MRI.createVirtualRegister(&AArch64::GPR32commonRegClass);
1050 BuildMI(MBB, MI, DL, get(ExtOpc), Reg).addReg(Cond[3].getReg());
1051 if (ExtOpc != AArch64::ANDWri)
1052 MBBI.addImm(0);
1053 MBBI.addImm(ExtBits);
1054 }
1055
1056 // Now, subs with an extended second operand
1058 MRI.constrainRegClass(Reg, &AArch64::GPR32commonRegClass);
1059 AArch64_AM::ShiftExtendType ExtendType =
1061 assert(isValidCBExtend(Cond[1].getImm(), ExtendType) &&
1062 "Unexpected compare-and-branch instruction for extend type");
1063 BuildMI(MBB, MI, DL, get(AArch64::SUBSWrx), AArch64::WZR)
1064 .addReg(Reg)
1065 .addReg(Cond[4].getReg())
1066 .addImm(AArch64_AM::getArithExtendImm(ExtendType, 0));
1067 } // If no extension is needed, just a regular subs
1068 else {
1069 BuildMI(MBB, MI, DL, get(AArch64::SUBSWrr), AArch64::WZR)
1070 .addReg(Reg)
1071 .addReg(Cond[4].getReg());
1072 }
1073
1074 CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
1075 } break;
1076 }
1077 return CC;
1078}
1079
1081 const TargetInstrInfo &TII) {
1082 for (MachineInstr &MI : MBB->terminators()) {
1083 unsigned Opc = MI.getOpcode();
1084 switch (Opc) {
1085 case AArch64::CBZW:
1086 case AArch64::CBZX:
1087 case AArch64::TBZW:
1088 case AArch64::TBZX:
1089 // CBZ/TBZ with WZR/XZR -> unconditional B
1090 if (MI.getOperand(0).getReg() == AArch64::WZR ||
1091 MI.getOperand(0).getReg() == AArch64::XZR) {
1092 DEBUG_WITH_TYPE("optimizeTerminators",
1093 dbgs() << "Removing always taken branch: " << MI);
1094 MachineBasicBlock *Target = TII.getBranchDestBlock(MI);
1095 SmallVector<MachineBasicBlock *> Succs(MBB->successors());
1096 for (auto *S : Succs)
1097 if (S != Target)
1098 MBB->removeSuccessor(S);
1099 DebugLoc DL = MI.getDebugLoc();
1100 while (MBB->rbegin() != &MI)
1101 MBB->rbegin()->eraseFromParent();
1102 MI.eraseFromParent();
1103 BuildMI(MBB, DL, TII.get(AArch64::B)).addMBB(Target);
1104 return true;
1105 }
1106 break;
1107 case AArch64::CBNZW:
1108 case AArch64::CBNZX:
1109 case AArch64::TBNZW:
1110 case AArch64::TBNZX:
1111 // CBNZ/TBNZ with WZR/XZR -> never taken, remove branch and successor
1112 if (MI.getOperand(0).getReg() == AArch64::WZR ||
1113 MI.getOperand(0).getReg() == AArch64::XZR) {
1114 DEBUG_WITH_TYPE("optimizeTerminators",
1115 dbgs() << "Removing never taken branch: " << MI);
1116 MachineBasicBlock *Target = TII.getBranchDestBlock(MI);
1117 MI.getParent()->removeSuccessor(Target);
1118 MI.eraseFromParent();
1119 return true;
1120 }
1121 break;
1122 }
1123 }
1124 return false;
1125}
1126
1127// Find the original register that VReg is copied from.
1128static unsigned removeCopies(const MachineRegisterInfo &MRI, unsigned VReg) {
1129 while (Register::isVirtualRegister(VReg)) {
1130 const MachineInstr *DefMI = MRI.getVRegDef(VReg);
1131 if (!DefMI || !DefMI->isFullCopy())
1132 return VReg;
1133 VReg = DefMI->getOperand(1).getReg();
1134 }
1135 return VReg;
1136}
1137
1138// Determine if VReg is defined by an instruction that can be folded into a
1139// csel instruction. If so, return the folded opcode, and the replacement
1140// register.
1141static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg,
1142 unsigned *NewReg = nullptr) {
1143 VReg = removeCopies(MRI, VReg);
1144 if (!Register::isVirtualRegister(VReg))
1145 return 0;
1146
1147 bool Is64Bit = AArch64::GPR64allRegClass.hasSubClassEq(MRI.getRegClass(VReg));
1148 const MachineInstr *DefMI = MRI.getVRegDef(VReg);
1149 if (!DefMI)
1150 return 0;
1151 unsigned Opc = 0;
1152 unsigned SrcReg = 0;
1153 switch (DefMI->getOpcode()) {
1154 case AArch64::SUBREG_TO_REG:
1155 // Check for the following way to define an 64-bit immediate:
1156 // %0:gpr32 = MOVi32imm 1
1157 // %1:gpr64 = SUBREG_TO_REG %0:gpr32, %subreg.sub_32
1158 if (!DefMI->getOperand(1).isReg())
1159 return 0;
1160 if (!DefMI->getOperand(2).isImm() ||
1161 DefMI->getOperand(2).getImm() != AArch64::sub_32)
1162 return 0;
1163 DefMI = MRI.getVRegDef(DefMI->getOperand(1).getReg());
1164 if (DefMI->getOpcode() != AArch64::MOVi32imm)
1165 return 0;
1166 if (!DefMI->getOperand(1).isImm() || DefMI->getOperand(1).getImm() != 1)
1167 return 0;
1168 assert(Is64Bit);
1169 SrcReg = AArch64::XZR;
1170 Opc = AArch64::CSINCXr;
1171 break;
1172
1173 case AArch64::MOVi32imm:
1174 case AArch64::MOVi64imm:
1175 if (!DefMI->getOperand(1).isImm() || DefMI->getOperand(1).getImm() != 1)
1176 return 0;
1177 SrcReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1178 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
1179 break;
1180
1181 case AArch64::ADDSXri:
1182 case AArch64::ADDSWri:
1183 // if NZCV is used, do not fold.
1184 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
1185 true) == -1)
1186 return 0;
1187 // fall-through to ADDXri and ADDWri.
1188 [[fallthrough]];
1189 case AArch64::ADDXri:
1190 case AArch64::ADDWri:
1191 // add x, 1 -> csinc.
1192 if (!DefMI->getOperand(2).isImm() || DefMI->getOperand(2).getImm() != 1 ||
1193 DefMI->getOperand(3).getImm() != 0)
1194 return 0;
1195 SrcReg = DefMI->getOperand(1).getReg();
1196 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
1197 break;
1198
1199 case AArch64::ORNXrr:
1200 case AArch64::ORNWrr: {
1201 // not x -> csinv, represented as orn dst, xzr, src.
1202 unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
1203 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
1204 return 0;
1205 SrcReg = DefMI->getOperand(2).getReg();
1206 Opc = Is64Bit ? AArch64::CSINVXr : AArch64::CSINVWr;
1207 break;
1208 }
1209
1210 case AArch64::SUBSXrr:
1211 case AArch64::SUBSWrr:
1212 // if NZCV is used, do not fold.
1213 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
1214 true) == -1)
1215 return 0;
1216 // fall-through to SUBXrr and SUBWrr.
1217 [[fallthrough]];
1218 case AArch64::SUBXrr:
1219 case AArch64::SUBWrr: {
1220 // neg x -> csneg, represented as sub dst, xzr, src.
1221 unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
1222 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
1223 return 0;
1224 SrcReg = DefMI->getOperand(2).getReg();
1225 Opc = Is64Bit ? AArch64::CSNEGXr : AArch64::CSNEGWr;
1226 break;
1227 }
1228 default:
1229 return 0;
1230 }
1231 assert(Opc && SrcReg && "Missing parameters");
1232
1233 if (NewReg)
1234 *NewReg = SrcReg;
1235 return Opc;
1236}
1237
1240 Register DstReg, Register TrueReg,
1241 Register FalseReg, int &CondCycles,
1242 int &TrueCycles,
1243 int &FalseCycles) const {
1244 // Check register classes.
1245 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
1246 const TargetRegisterClass *RC =
1247 RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg));
1248 if (!RC)
1249 return false;
1250
1251 // Also need to check the dest regclass, in case we're trying to optimize
1252 // something like:
1253 // %1(gpr) = PHI %2(fpr), bb1, %(fpr), bb2
1254 if (!RI.getCommonSubClass(RC, MRI.getRegClass(DstReg)))
1255 return false;
1256
1257 // Expanding cbz/tbz requires an extra cycle of latency on the condition.
1258 unsigned ExtraCondLat = Cond.size() != 1;
1259
1260 // GPRs are handled by csel.
1261 // FIXME: Fold in x+1, -x, and ~x when applicable.
1262 if (AArch64::GPR64allRegClass.hasSubClassEq(RC) ||
1263 AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
1264 // Single-cycle csel, csinc, csinv, and csneg.
1265 CondCycles = 1 + ExtraCondLat;
1266 TrueCycles = FalseCycles = 1;
1267 if (canFoldIntoCSel(MRI, TrueReg))
1268 TrueCycles = 0;
1269 else if (canFoldIntoCSel(MRI, FalseReg))
1270 FalseCycles = 0;
1271 return true;
1272 }
1273
1274 // Scalar floating point is handled by fcsel.
1275 // FIXME: Form fabs, fmin, and fmax when applicable.
1276 if (AArch64::FPR64RegClass.hasSubClassEq(RC) ||
1277 AArch64::FPR32RegClass.hasSubClassEq(RC)) {
1278 CondCycles = 5 + ExtraCondLat;
1279 TrueCycles = FalseCycles = 2;
1280 return true;
1281 }
1282
1283 // No single conditional move for a 128-bit vector, but we can emit a sequence
1284 // of csetm (~1), dup (~5, cross domain), bsl (~2).
1285 if (AArch64::FPR128RegClass.hasSubClassEq(RC) &&
1286 Subtarget.isNeonAvailable() &&
1287 !MBB.getParent()->getFunction().hasMinSize()) {
1288 CondCycles = 8 + ExtraCondLat;
1289 TrueCycles = FalseCycles = 2;
1290 return true;
1291 }
1292
1293 return false;
1294}
1295
1298 const DebugLoc &DL, Register DstReg,
1300 Register TrueReg, Register FalseReg) const {
1301
1302 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
1304
1305 // A 128-bit vector has no conditional move so blend the operands with a mask
1306 // built from the flags.
1307 if (MRI.constrainRegClass(DstReg, &AArch64::FPR128RegClass)) {
1308 assert(Subtarget.isNeonAvailable() && "Expected NEON for a vector select");
1309 MRI.constrainRegClass(TrueReg, &AArch64::FPR128RegClass);
1310 MRI.constrainRegClass(FalseReg, &AArch64::FPR128RegClass);
1311 Register CondSet = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
1312 BuildMI(MBB, I, DL, get(AArch64::CSINVXr), CondSet)
1313 .addReg(AArch64::XZR)
1314 .addReg(AArch64::XZR)
1316 Register Mask = MRI.createVirtualRegister(&AArch64::FPR128RegClass);
1317 BuildMI(MBB, I, DL, get(AArch64::DUPv2i64gpr), Mask).addReg(CondSet);
1318 BuildMI(MBB, I, DL, get(AArch64::BSPv16i8), DstReg)
1319 .addReg(Mask)
1320 .addReg(TrueReg)
1321 .addReg(FalseReg);
1322 return;
1323 }
1324
1325 unsigned Opc = 0;
1326 const TargetRegisterClass *RC = nullptr;
1327 bool TryFold = false;
1328 if (MRI.constrainRegClass(DstReg, &AArch64::GPR64RegClass)) {
1329 RC = &AArch64::GPR64RegClass;
1330 Opc = AArch64::CSELXr;
1331 TryFold = true;
1332 } else if (MRI.constrainRegClass(DstReg, &AArch64::GPR32RegClass)) {
1333 RC = &AArch64::GPR32RegClass;
1334 Opc = AArch64::CSELWr;
1335 TryFold = true;
1336 } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR64RegClass)) {
1337 RC = &AArch64::FPR64RegClass;
1338 Opc = AArch64::FCSELDrrr;
1339 } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR32RegClass)) {
1340 RC = &AArch64::FPR32RegClass;
1341 Opc = AArch64::FCSELSrrr;
1342 }
1343 assert(RC && "Unsupported regclass");
1344
1345 // Try folding simple instructions into the csel.
1346 if (TryFold) {
1347 unsigned NewReg = 0;
1348 unsigned FoldedOpc = canFoldIntoCSel(MRI, TrueReg, &NewReg);
1349 if (FoldedOpc) {
1350 // The folded opcodes csinc, csinc and csneg apply the operation to
1351 // FalseReg, so we need to invert the condition.
1353 TrueReg = FalseReg;
1354 } else
1355 FoldedOpc = canFoldIntoCSel(MRI, FalseReg, &NewReg);
1356
1357 // Fold the operation. Leave any dead instructions for DCE to clean up.
1358 if (FoldedOpc) {
1359 FalseReg = NewReg;
1360 Opc = FoldedOpc;
1361 // Extend the live range of NewReg.
1362 MRI.clearKillFlags(NewReg);
1363 }
1364 }
1365
1366 // Pull all virtual register into the appropriate class.
1367 MRI.constrainRegClass(TrueReg, RC);
1368 // FalseReg might be WZR or XZR if the folded operand is a literal 1.
1369 assert(
1370 (FalseReg.isVirtual() || FalseReg == AArch64::WZR ||
1371 FalseReg == AArch64::XZR) &&
1372 "FalseReg was folded into a non-virtual register other than WZR or XZR");
1373 if (FalseReg.isVirtual())
1374 MRI.constrainRegClass(FalseReg, RC);
1375
1376 // Insert the csel.
1377 BuildMI(MBB, I, DL, get(Opc), DstReg)
1378 .addReg(TrueReg)
1379 .addReg(FalseReg)
1380 .addImm(CC);
1381}
1382
1383// Return true if Imm can be loaded into a register by a "cheap" sequence of
1384// instructions. For now, "cheap" means at most two instructions.
1385static bool isCheapImmediate(const MachineInstr &MI, unsigned BitSize) {
1386 if (BitSize == 32)
1387 return true;
1388
1389 assert(BitSize == 64 && "Only bit sizes of 32 or 64 allowed");
1390 uint64_t Imm = static_cast<uint64_t>(MI.getOperand(1).getImm());
1392 AArch64_IMM::expandMOVImm(Imm, BitSize, Is);
1393
1394 return Is.size() <= 2;
1395}
1396
1397// Check if a COPY instruction is cheap.
1398static bool isCheapCopy(const MachineInstr &MI, const AArch64RegisterInfo &RI) {
1399 assert(MI.isCopy() && "Expected COPY instruction");
1400 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
1401
1402 // Cross-bank copies (e.g., between GPR and FPR) are expensive on AArch64,
1403 // typically requiring an FMOV instruction with a 2-6 cycle latency.
1404 auto GetRegClass = [&](Register Reg) -> const TargetRegisterClass * {
1405 if (Reg.isVirtual())
1406 return MRI.getRegClass(Reg);
1407 if (Reg.isPhysical())
1408 return RI.getMinimalPhysRegClass(Reg);
1409 return nullptr;
1410 };
1411 const TargetRegisterClass *DstRC = GetRegClass(MI.getOperand(0).getReg());
1412 const TargetRegisterClass *SrcRC = GetRegClass(MI.getOperand(1).getReg());
1413 if (DstRC && SrcRC && !RI.getCommonSubClass(DstRC, SrcRC))
1414 return false;
1415
1416 return MI.isAsCheapAsAMove();
1417}
1418
1419// FIXME: this implementation should be micro-architecture dependent, so a
1420// micro-architecture target hook should be introduced here in future.
1422 if (Subtarget.hasExynosCheapAsMoveHandling()) {
1423 if (isExynosCheapAsMove(MI))
1424 return true;
1425 return MI.isAsCheapAsAMove();
1426 }
1427
1428 switch (MI.getOpcode()) {
1429 default:
1430 return MI.isAsCheapAsAMove();
1431
1432 case TargetOpcode::COPY:
1433 return isCheapCopy(MI, RI);
1434
1435 case AArch64::ADDWrs:
1436 case AArch64::ADDXrs:
1437 case AArch64::SUBWrs:
1438 case AArch64::SUBXrs:
1439 return Subtarget.hasALULSLFast() && MI.getOperand(3).getImm() <= 4;
1440
1441 // If MOVi32imm or MOVi64imm can be expanded into ORRWri or
1442 // ORRXri, it is as cheap as MOV.
1443 // Likewise if it can be expanded to MOVZ/MOVN/MOVK.
1444 case AArch64::MOVi32imm:
1445 return isCheapImmediate(MI, 32);
1446 case AArch64::MOVi64imm:
1447 return isCheapImmediate(MI, 64);
1448 }
1449}
1450
1451bool AArch64InstrInfo::isFalkorShiftExtFast(const MachineInstr &MI) {
1452 switch (MI.getOpcode()) {
1453 default:
1454 return false;
1455
1456 case AArch64::ADDWrs:
1457 case AArch64::ADDXrs:
1458 case AArch64::ADDSWrs:
1459 case AArch64::ADDSXrs: {
1460 unsigned Imm = MI.getOperand(3).getImm();
1461 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1462 if (ShiftVal == 0)
1463 return true;
1464 return AArch64_AM::getShiftType(Imm) == AArch64_AM::LSL && ShiftVal <= 5;
1465 }
1466
1467 case AArch64::ADDWrx:
1468 case AArch64::ADDXrx:
1469 case AArch64::ADDXrx64:
1470 case AArch64::ADDSWrx:
1471 case AArch64::ADDSXrx:
1472 case AArch64::ADDSXrx64: {
1473 unsigned Imm = MI.getOperand(3).getImm();
1475 default:
1476 return false;
1477 case AArch64_AM::UXTB:
1478 case AArch64_AM::UXTH:
1479 case AArch64_AM::UXTW:
1480 case AArch64_AM::UXTX:
1482 }
1483 }
1484
1485 case AArch64::SUBWrs:
1486 case AArch64::SUBSWrs: {
1487 unsigned Imm = MI.getOperand(3).getImm();
1488 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1489 return ShiftVal == 0 ||
1490 (AArch64_AM::getShiftType(Imm) == AArch64_AM::ASR && ShiftVal == 31);
1491 }
1492
1493 case AArch64::SUBXrs:
1494 case AArch64::SUBSXrs: {
1495 unsigned Imm = MI.getOperand(3).getImm();
1496 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1497 return ShiftVal == 0 ||
1498 (AArch64_AM::getShiftType(Imm) == AArch64_AM::ASR && ShiftVal == 63);
1499 }
1500
1501 case AArch64::SUBWrx:
1502 case AArch64::SUBXrx:
1503 case AArch64::SUBXrx64:
1504 case AArch64::SUBSWrx:
1505 case AArch64::SUBSXrx:
1506 case AArch64::SUBSXrx64: {
1507 unsigned Imm = MI.getOperand(3).getImm();
1509 default:
1510 return false;
1511 case AArch64_AM::UXTB:
1512 case AArch64_AM::UXTH:
1513 case AArch64_AM::UXTW:
1514 case AArch64_AM::UXTX:
1516 }
1517 }
1518
1519 case AArch64::LDRBBroW:
1520 case AArch64::LDRBBroX:
1521 case AArch64::LDRBroW:
1522 case AArch64::LDRBroX:
1523 case AArch64::LDRDroW:
1524 case AArch64::LDRDroX:
1525 case AArch64::LDRHHroW:
1526 case AArch64::LDRHHroX:
1527 case AArch64::LDRHroW:
1528 case AArch64::LDRHroX:
1529 case AArch64::LDRQroW:
1530 case AArch64::LDRQroX:
1531 case AArch64::LDRSBWroW:
1532 case AArch64::LDRSBWroX:
1533 case AArch64::LDRSBXroW:
1534 case AArch64::LDRSBXroX:
1535 case AArch64::LDRSHWroW:
1536 case AArch64::LDRSHWroX:
1537 case AArch64::LDRSHXroW:
1538 case AArch64::LDRSHXroX:
1539 case AArch64::LDRSWroW:
1540 case AArch64::LDRSWroX:
1541 case AArch64::LDRSroW:
1542 case AArch64::LDRSroX:
1543 case AArch64::LDRWroW:
1544 case AArch64::LDRWroX:
1545 case AArch64::LDRXroW:
1546 case AArch64::LDRXroX:
1547 case AArch64::PRFMroW:
1548 case AArch64::PRFMroX:
1549 case AArch64::STRBBroW:
1550 case AArch64::STRBBroX:
1551 case AArch64::STRBroW:
1552 case AArch64::STRBroX:
1553 case AArch64::STRDroW:
1554 case AArch64::STRDroX:
1555 case AArch64::STRHHroW:
1556 case AArch64::STRHHroX:
1557 case AArch64::STRHroW:
1558 case AArch64::STRHroX:
1559 case AArch64::STRQroW:
1560 case AArch64::STRQroX:
1561 case AArch64::STRSroW:
1562 case AArch64::STRSroX:
1563 case AArch64::STRWroW:
1564 case AArch64::STRWroX:
1565 case AArch64::STRXroW:
1566 case AArch64::STRXroX: {
1567 unsigned IsSigned = MI.getOperand(3).getImm();
1568 return !IsSigned;
1569 }
1570 }
1571}
1572
1573bool AArch64InstrInfo::isSEHInstruction(const MachineInstr &MI) {
1574 unsigned Opc = MI.getOpcode();
1575 switch (Opc) {
1576 default:
1577 return false;
1578 case AArch64::SEH_StackAlloc:
1579 case AArch64::SEH_SaveFPLR:
1580 case AArch64::SEH_SaveFPLR_X:
1581 case AArch64::SEH_SaveReg:
1582 case AArch64::SEH_SaveReg_X:
1583 case AArch64::SEH_SaveRegP:
1584 case AArch64::SEH_SaveRegP_X:
1585 case AArch64::SEH_SaveFReg:
1586 case AArch64::SEH_SaveFReg_X:
1587 case AArch64::SEH_SaveFRegP:
1588 case AArch64::SEH_SaveFRegP_X:
1589 case AArch64::SEH_SetFP:
1590 case AArch64::SEH_AddFP:
1591 case AArch64::SEH_Nop:
1592 case AArch64::SEH_PrologEnd:
1593 case AArch64::SEH_EpilogStart:
1594 case AArch64::SEH_EpilogEnd:
1595 case AArch64::SEH_PACSignLR:
1596 case AArch64::SEH_SaveAnyRegI:
1597 case AArch64::SEH_SaveAnyRegIP:
1598 case AArch64::SEH_SaveAnyRegQP:
1599 case AArch64::SEH_SaveAnyRegQPX:
1600 case AArch64::SEH_AllocZ:
1601 case AArch64::SEH_SaveZReg:
1602 case AArch64::SEH_SavePReg:
1603 return true;
1604 }
1605}
1606
1608 Register &SrcReg, Register &DstReg,
1609 unsigned &SubIdx) const {
1610 switch (MI.getOpcode()) {
1611 default:
1612 return false;
1613 case AArch64::SBFMXri: // aka sxtw
1614 case AArch64::UBFMXri: // aka uxtw
1615 // Check for the 32 -> 64 bit extension case, these instructions can do
1616 // much more.
1617 if (MI.getOperand(2).getImm() != 0 || MI.getOperand(3).getImm() != 31)
1618 return false;
1619 // This is a signed or unsigned 32 -> 64 bit extension.
1620 SrcReg = MI.getOperand(1).getReg();
1621 DstReg = MI.getOperand(0).getReg();
1622 SubIdx = AArch64::sub_32;
1623 return true;
1624 }
1625}
1626
1628 const MachineInstr &MIa, const MachineInstr &MIb) const {
1630 const MachineOperand *BaseOpA = nullptr, *BaseOpB = nullptr;
1631 int64_t OffsetA = 0, OffsetB = 0;
1632 TypeSize WidthA(0, false), WidthB(0, false);
1633 bool OffsetAIsScalable = false, OffsetBIsScalable = false;
1634
1635 assert(MIa.mayLoadOrStore() && "MIa must be a load or store.");
1636 assert(MIb.mayLoadOrStore() && "MIb must be a load or store.");
1637
1640 return false;
1641
1642 // Retrieve the base, offset from the base and width. Width
1643 // is the size of memory that is being loaded/stored (e.g. 1, 2, 4, 8). If
1644 // base are identical, and the offset of a lower memory access +
1645 // the width doesn't overlap the offset of a higher memory access,
1646 // then the memory accesses are different.
1647 // If OffsetAIsScalable and OffsetBIsScalable are both true, they
1648 // are assumed to have the same scale (vscale).
1649 if (getMemOperandWithOffsetWidth(MIa, BaseOpA, OffsetA, OffsetAIsScalable,
1650 WidthA, TRI) &&
1651 getMemOperandWithOffsetWidth(MIb, BaseOpB, OffsetB, OffsetBIsScalable,
1652 WidthB, TRI)) {
1653 if (BaseOpA->isIdenticalTo(*BaseOpB) &&
1654 OffsetAIsScalable == OffsetBIsScalable) {
1655 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
1656 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
1657 TypeSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
1658 if (LowWidth.isScalable() == OffsetAIsScalable &&
1659 LowOffset + (int)LowWidth.getKnownMinValue() <= HighOffset)
1660 return true;
1661 }
1662 }
1663 return false;
1664}
1665
1667 const MachineBasicBlock *MBB,
1668 const MachineFunction &MF) const {
1670 return true;
1671
1672 // Do not move an instruction that can be recognized as a branch target.
1673 if (hasBTISemantics(MI))
1674 return true;
1675
1676 switch (MI.getOpcode()) {
1677 case AArch64::HINT:
1678 // CSDB hints are scheduling barriers.
1679 if (MI.getOperand(0).getImm() == 0x14)
1680 return true;
1681 break;
1682 case AArch64::DSB:
1683 case AArch64::ISB:
1684 // DSB and ISB also are scheduling barriers.
1685 return true;
1686 case AArch64::MSRpstatesvcrImm1:
1687 // SMSTART and SMSTOP are also scheduling barriers.
1688 return true;
1689 default:;
1690 }
1691 if (isSEHInstruction(MI))
1692 return true;
1693 auto Next = std::next(MI.getIterator());
1694 return Next != MBB->end() && Next->isCFIInstruction();
1695}
1696
1697/// analyzeCompare - For a comparison instruction, return the source registers
1698/// in SrcReg and SrcReg2, and the value it compares against in CmpValue.
1699/// Return true if the comparison instruction can be analyzed.
1701 Register &SrcReg2, int64_t &CmpMask,
1702 int64_t &CmpValue) const {
1703 // The first operand can be a frame index where we'd normally expect a
1704 // register.
1705 // FIXME: Pass subregisters out of analyzeCompare
1706 assert(MI.getNumOperands() >= 2 && "All AArch64 cmps should have 2 operands");
1707 if (!MI.getOperand(1).isReg() || MI.getOperand(1).getSubReg())
1708 return false;
1709
1710 switch (MI.getOpcode()) {
1711 default:
1712 break;
1713 case AArch64::PTEST_PP:
1714 case AArch64::PTEST_PP_ANY:
1715 case AArch64::PTEST_PP_FIRST:
1716 SrcReg = MI.getOperand(0).getReg();
1717 SrcReg2 = MI.getOperand(1).getReg();
1718 if (MI.getOperand(2).getSubReg())
1719 return false;
1720
1721 // Not sure about the mask and value for now...
1722 CmpMask = ~0;
1723 CmpValue = 0;
1724 return true;
1725 case AArch64::SUBSWrr:
1726 case AArch64::SUBSWrs:
1727 case AArch64::SUBSWrx:
1728 case AArch64::SUBSXrr:
1729 case AArch64::SUBSXrs:
1730 case AArch64::SUBSXrx:
1731 case AArch64::ADDSWrr:
1732 case AArch64::ADDSWrs:
1733 case AArch64::ADDSWrx:
1734 case AArch64::ADDSXrr:
1735 case AArch64::ADDSXrs:
1736 case AArch64::ADDSXrx:
1737 // Replace SUBSWrr with SUBWrr if NZCV is not used.
1738 SrcReg = MI.getOperand(1).getReg();
1739 SrcReg2 = MI.getOperand(2).getReg();
1740
1741 // FIXME: Pass subregisters out of analyzeCompare
1742 if (MI.getOperand(2).getSubReg())
1743 return false;
1744
1745 CmpMask = ~0;
1746 CmpValue = 0;
1747 return true;
1748 case AArch64::SUBSWri:
1749 case AArch64::ADDSWri:
1750 case AArch64::SUBSXri:
1751 case AArch64::ADDSXri:
1752 SrcReg = MI.getOperand(1).getReg();
1753 SrcReg2 = 0;
1754 CmpMask = ~0;
1755 CmpValue = MI.getOperand(2).getImm();
1756 return true;
1757 case AArch64::ANDSWri:
1758 case AArch64::ANDSXri:
1759 // ANDS does not use the same encoding scheme as the others xxxS
1760 // instructions.
1761 SrcReg = MI.getOperand(1).getReg();
1762 SrcReg2 = 0;
1763 CmpMask = ~0;
1765 MI.getOperand(2).getImm(),
1766 MI.getOpcode() == AArch64::ANDSWri ? 32 : 64);
1767 return true;
1768 }
1769
1770 return false;
1771}
1772
1774 MachineBasicBlock *MBB = Instr.getParent();
1775 assert(MBB && "Can't get MachineBasicBlock here");
1776 MachineFunction *MF = MBB->getParent();
1777 assert(MF && "Can't get MachineFunction here");
1780 MachineRegisterInfo *MRI = &MF->getRegInfo();
1781
1782 for (unsigned OpIdx = 0, EndIdx = Instr.getNumOperands(); OpIdx < EndIdx;
1783 ++OpIdx) {
1784 MachineOperand &MO = Instr.getOperand(OpIdx);
1785 const TargetRegisterClass *OpRegCstraints =
1786 Instr.getRegClassConstraint(OpIdx, TII, TRI);
1787
1788 // If there's no constraint, there's nothing to do.
1789 if (!OpRegCstraints)
1790 continue;
1791 // If the operand is a frame index, there's nothing to do here.
1792 // A frame index operand will resolve correctly during PEI.
1793 if (MO.isFI())
1794 continue;
1795
1796 assert(MO.isReg() &&
1797 "Operand has register constraints without being a register!");
1798
1799 Register Reg = MO.getReg();
1800 if (Reg.isPhysical()) {
1801 if (!OpRegCstraints->contains(Reg))
1802 return false;
1803 } else if (!OpRegCstraints->hasSubClassEq(MRI->getRegClass(Reg)) &&
1804 !MRI->constrainRegClass(Reg, OpRegCstraints))
1805 return false;
1806 }
1807
1808 return true;
1809}
1810
1811/// Return the opcode that does not set flags when possible - otherwise
1812/// return the original opcode. The caller is responsible to do the actual
1813/// substitution and legality checking.
1815 // Don't convert all compare instructions, because for some the zero register
1816 // encoding becomes the sp register.
1817 bool MIDefinesZeroReg = false;
1818 if (MI.definesRegister(AArch64::WZR, /*TRI=*/nullptr) ||
1819 MI.definesRegister(AArch64::XZR, /*TRI=*/nullptr))
1820 MIDefinesZeroReg = true;
1821
1822 switch (MI.getOpcode()) {
1823 default:
1824 return MI.getOpcode();
1825 case AArch64::ADDSWrr:
1826 return AArch64::ADDWrr;
1827 case AArch64::ADDSWri:
1828 return MIDefinesZeroReg ? AArch64::ADDSWri : AArch64::ADDWri;
1829 case AArch64::ADDSWrs:
1830 return MIDefinesZeroReg ? AArch64::ADDSWrs : AArch64::ADDWrs;
1831 case AArch64::ADDSWrx:
1832 return AArch64::ADDWrx;
1833 case AArch64::ADDSXrr:
1834 return AArch64::ADDXrr;
1835 case AArch64::ADDSXri:
1836 return MIDefinesZeroReg ? AArch64::ADDSXri : AArch64::ADDXri;
1837 case AArch64::ADDSXrs:
1838 return MIDefinesZeroReg ? AArch64::ADDSXrs : AArch64::ADDXrs;
1839 case AArch64::ADDSXrx:
1840 return AArch64::ADDXrx;
1841 case AArch64::SUBSWrr:
1842 return AArch64::SUBWrr;
1843 case AArch64::SUBSWri:
1844 return MIDefinesZeroReg ? AArch64::SUBSWri : AArch64::SUBWri;
1845 case AArch64::SUBSWrs:
1846 return MIDefinesZeroReg ? AArch64::SUBSWrs : AArch64::SUBWrs;
1847 case AArch64::SUBSWrx:
1848 return AArch64::SUBWrx;
1849 case AArch64::SUBSXrr:
1850 return AArch64::SUBXrr;
1851 case AArch64::SUBSXri:
1852 return MIDefinesZeroReg ? AArch64::SUBSXri : AArch64::SUBXri;
1853 case AArch64::SUBSXrs:
1854 return MIDefinesZeroReg ? AArch64::SUBSXrs : AArch64::SUBXrs;
1855 case AArch64::SUBSXrx:
1856 return AArch64::SUBXrx;
1857 }
1858}
1859
1860enum AccessKind { AK_Write = 0x01, AK_Read = 0x10, AK_All = 0x11 };
1861
1862/// True when condition flags are accessed (either by writing or reading)
1863/// on the instruction trace starting at From and ending at To.
1864///
1865/// Note: If From and To are from different blocks it's assumed CC are accessed
1866/// on the path.
1869 const TargetRegisterInfo *TRI, const AccessKind AccessToCheck = AK_All) {
1870 // Early exit if To is at the beginning of the BB.
1871 if (To == To->getParent()->begin())
1872 return true;
1873
1874 // Check whether the instructions are in the same basic block
1875 // If not, assume the condition flags might get modified somewhere.
1876 if (To->getParent() != From->getParent())
1877 return true;
1878
1879 // From must be above To.
1880 assert(std::any_of(
1881 ++To.getReverse(), To->getParent()->rend(),
1882 [From](MachineInstr &MI) { return MI.getIterator() == From; }));
1883
1884 // We iterate backward starting at \p To until we hit \p From.
1885 for (const MachineInstr &Instr :
1887 if (((AccessToCheck & AK_Write) &&
1888 Instr.modifiesRegister(AArch64::NZCV, TRI)) ||
1889 ((AccessToCheck & AK_Read) && Instr.readsRegister(AArch64::NZCV, TRI)))
1890 return true;
1891 }
1892 return false;
1893}
1894
1895std::optional<unsigned>
1896AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1897 MachineInstr *Pred,
1898 const MachineRegisterInfo *MRI) const {
1899 unsigned MaskOpcode = Mask->getOpcode();
1900 unsigned PredOpcode = Pred->getOpcode();
1901 bool PredIsPTestLike = isPTestLikeOpcode(PredOpcode);
1902 bool PredIsWhileLike = isWhileOpcode(PredOpcode);
1903
1904 if (PredIsWhileLike) {
1905 // For PTEST(PG, PG), PTEST is redundant when PG is the result of a WHILEcc
1906 // instruction and the condition is "any" since WHILcc does an implicit
1907 // PTEST(ALL, PG) check and PG is always a subset of ALL.
1908 if ((Mask == Pred) && PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1909 return PredOpcode;
1910
1911 // For PTEST(PTRUE_ALL, WHILE), if the element size matches, the PTEST is
1912 // redundant since WHILE performs an implicit PTEST with an all active
1913 // mask.
1914 if (isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31 &&
1915 getElementSizeForOpcode(MaskOpcode) ==
1916 getElementSizeForOpcode(PredOpcode))
1917 return PredOpcode;
1918
1919 // For PTEST_FIRST(PTRUE_ALL, WHILE), the PTEST_FIRST is redundant since
1920 // WHILEcc performs an implicit PTEST with an all active mask, setting
1921 // the N flag as the PTEST_FIRST would.
1922 if (PTest->getOpcode() == AArch64::PTEST_PP_FIRST &&
1923 isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31)
1924 return PredOpcode;
1925
1926 return {};
1927 }
1928
1929 if (PredIsPTestLike) {
1930 // For PTEST(PG, PG), PTEST is redundant when PG is the result of an
1931 // instruction that sets the flags as PTEST would and the condition is
1932 // "any" since PG is always a subset of the governing predicate of the
1933 // ptest-like instruction.
1934 if ((Mask == Pred) && PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1935 return PredOpcode;
1936
1937 auto PTestLikeMask = MRI->getUniqueVRegDef(Pred->getOperand(1).getReg());
1938
1939 // If the PTEST like instruction's general predicate is not `Mask`, attempt
1940 // to look through a copy and try again. This is because some instructions
1941 // take a predicate whose register class is a subset of its result class.
1942 if (Mask != PTestLikeMask && PTestLikeMask->isFullCopy() &&
1943 PTestLikeMask->getOperand(1).getReg().isVirtual())
1944 PTestLikeMask =
1945 MRI->getUniqueVRegDef(PTestLikeMask->getOperand(1).getReg());
1946
1947 // For PTEST(PTRUE_ALL, PTEST_LIKE), the PTEST is redundant if the
1948 // the element size matches and either the PTEST_LIKE instruction uses
1949 // the same all active mask or the condition is "any".
1950 if (isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31 &&
1951 getElementSizeForOpcode(MaskOpcode) ==
1952 getElementSizeForOpcode(PredOpcode)) {
1953 if (Mask == PTestLikeMask || PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1954 return PredOpcode;
1955 }
1956
1957 // For PTEST(PG, PTEST_LIKE(PG, ...)), the PTEST is redundant since the
1958 // flags are set based on the same mask 'PG', but PTEST_LIKE must operate
1959 // on 8-bit predicates like the PTEST. Otherwise, for instructions like
1960 // compare that also support 16/32/64-bit predicates, the implicit PTEST
1961 // performed by the compare could consider fewer lanes for these element
1962 // sizes.
1963 //
1964 // For example, consider
1965 //
1966 // ptrue p0.b ; P0=1111-1111-1111-1111
1967 // index z0.s, #0, #1 ; Z0=<0,1,2,3>
1968 // index z1.s, #1, #1 ; Z1=<1,2,3,4>
1969 // cmphi p1.s, p0/z, z1.s, z0.s ; P1=0001-0001-0001-0001
1970 // ; ^ last active
1971 // ptest p0, p1.b ; P1=0001-0001-0001-0001
1972 // ; ^ last active
1973 //
1974 // where the compare generates a canonical all active 32-bit predicate
1975 // (equivalent to 'ptrue p1.s, all'). The implicit PTEST sets the last
1976 // active flag, whereas the PTEST instruction with the same mask doesn't.
1977 // For PTEST_ANY this doesn't apply as the flags in this case would be
1978 // identical regardless of element size.
1979 uint64_t PredElementSize = getElementSizeForOpcode(PredOpcode);
1980 if (Mask == PTestLikeMask && (PredElementSize == AArch64::ElementSizeB ||
1981 PTest->getOpcode() == AArch64::PTEST_PP_ANY))
1982 return PredOpcode;
1983
1984 return {};
1985 }
1986
1987 // If OP in PTEST(PG, OP(PG, ...)) has a flag-setting variant change the
1988 // opcode so the PTEST becomes redundant.
1989 switch (PredOpcode) {
1990 case AArch64::AND_PPzPP:
1991 case AArch64::BIC_PPzPP:
1992 case AArch64::EOR_PPzPP:
1993 case AArch64::NAND_PPzPP:
1994 case AArch64::NOR_PPzPP:
1995 case AArch64::ORN_PPzPP:
1996 case AArch64::ORR_PPzPP:
1997 case AArch64::BRKA_PPzP:
1998 case AArch64::BRKPA_PPzPP:
1999 case AArch64::BRKB_PPzP:
2000 case AArch64::BRKPB_PPzPP:
2001 case AArch64::RDFFR_PPz: {
2002 // Check to see if our mask is the same. If not the resulting flag bits
2003 // may be different and we can't remove the ptest.
2004 auto *PredMask = MRI->getUniqueVRegDef(Pred->getOperand(1).getReg());
2005 if (Mask != PredMask)
2006 return {};
2007 break;
2008 }
2009 case AArch64::BRKN_PPzP: {
2010 // BRKN uses an all active implicit mask to set flags unlike the other
2011 // flag-setting instructions.
2012 // PTEST(PTRUE_B(31), BRKN(PG, A, B)) -> BRKNS(PG, A, B).
2013 if ((MaskOpcode != AArch64::PTRUE_B) ||
2014 (Mask->getOperand(1).getImm() != 31))
2015 return {};
2016 break;
2017 }
2018 case AArch64::PTRUE_B:
2019 // PTEST(OP=PTRUE_B(A), OP) -> PTRUES_B(A)
2020 break;
2021 default:
2022 // Bail out if we don't recognize the input
2023 return {};
2024 }
2025
2026 return convertToFlagSettingOpc(PredOpcode);
2027}
2028
2029/// optimizePTestInstr - Attempt to remove a ptest of a predicate-generating
2030/// operation which could set the flags in an identical manner
2031bool AArch64InstrInfo::optimizePTestInstr(
2032 MachineInstr *PTest, unsigned MaskReg, unsigned PredReg,
2033 const MachineRegisterInfo *MRI) const {
2034 auto *Mask = MRI->getUniqueVRegDef(MaskReg);
2035 auto *Pred = MRI->getUniqueVRegDef(PredReg);
2036
2037 if (Pred->isCopy() && PTest->getOpcode() == AArch64::PTEST_PP_FIRST) {
2038 // Instructions which return a multi-vector (e.g. WHILECC_x2) require copies
2039 // before the branch to extract each subregister.
2040 auto Op = Pred->getOperand(1);
2041 if (Op.isReg() && Op.getReg().isVirtual() &&
2042 Op.getSubReg() == AArch64::psub0)
2043 Pred = MRI->getUniqueVRegDef(Op.getReg());
2044 }
2045
2046 unsigned PredOpcode = Pred->getOpcode();
2047 auto NewOp = canRemovePTestInstr(PTest, Mask, Pred, MRI);
2048 if (!NewOp)
2049 return false;
2050
2051 const TargetRegisterInfo *TRI = &getRegisterInfo();
2052
2053 // If another instruction between Pred and PTest accesses flags, don't remove
2054 // the ptest or update the earlier instruction to modify them.
2055 if (areCFlagsAccessedBetweenInstrs(Pred, PTest, TRI))
2056 return false;
2057
2058 // If we pass all the checks, it's safe to remove the PTEST and use the flags
2059 // as they are prior to PTEST. Sometimes this requires the tested PTEST
2060 // operand to be replaced with an equivalent instruction that also sets the
2061 // flags.
2062 PTest->eraseFromParent();
2063 if (*NewOp != PredOpcode) {
2064 Pred->setDesc(get(*NewOp));
2065 bool succeeded = UpdateOperandRegClass(*Pred);
2066 (void)succeeded;
2067 assert(succeeded && "Operands have incompatible register classes!");
2068 Pred->addRegisterDefined(AArch64::NZCV, TRI);
2069 }
2070
2071 // Ensure that the flags def is live.
2072 if (Pred->registerDefIsDead(AArch64::NZCV, TRI)) {
2073 unsigned i = 0, e = Pred->getNumOperands();
2074 for (; i != e; ++i) {
2075 MachineOperand &MO = Pred->getOperand(i);
2076 if (MO.isReg() && MO.isDef() && MO.getReg() == AArch64::NZCV) {
2077 MO.setIsDead(false);
2078 break;
2079 }
2080 }
2081 }
2082 return true;
2083}
2084
2085/// Try to optimize a compare instruction. A compare instruction is an
2086/// instruction which produces AArch64::NZCV. It can be truly compare
2087/// instruction
2088/// when there are no uses of its destination register.
2089///
2090/// The following steps are tried in order:
2091/// 1. Convert CmpInstr into an unconditional version.
2092/// 2. Remove CmpInstr if above there is an instruction producing a needed
2093/// condition code or an instruction which can be converted into such an
2094/// instruction.
2095/// Only comparison with zero is supported.
2097 MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask,
2098 int64_t CmpValue, const MachineRegisterInfo *MRI) const {
2099 assert(CmpInstr.getParent());
2100 assert(MRI);
2101
2102 // Replace SUBSWrr with SUBWrr if NZCV is not used.
2103 int DeadNZCVIdx =
2104 CmpInstr.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true);
2105 if (DeadNZCVIdx != -1) {
2106 if (CmpInstr.definesRegister(AArch64::WZR, /*TRI=*/nullptr) ||
2107 CmpInstr.definesRegister(AArch64::XZR, /*TRI=*/nullptr)) {
2108 CmpInstr.eraseFromParent();
2109 return true;
2110 }
2111 unsigned Opc = CmpInstr.getOpcode();
2112 unsigned NewOpc = convertToNonFlagSettingOpc(CmpInstr);
2113 if (NewOpc == Opc)
2114 return false;
2115 const MCInstrDesc &MCID = get(NewOpc);
2116 CmpInstr.setDesc(MCID);
2117 CmpInstr.removeOperand(DeadNZCVIdx);
2118 bool succeeded = UpdateOperandRegClass(CmpInstr);
2119 (void)succeeded;
2120 assert(succeeded && "Some operands reg class are incompatible!");
2121 return true;
2122 }
2123
2124 if (CmpInstr.getOpcode() == AArch64::PTEST_PP ||
2125 CmpInstr.getOpcode() == AArch64::PTEST_PP_ANY ||
2126 CmpInstr.getOpcode() == AArch64::PTEST_PP_FIRST)
2127 return optimizePTestInstr(&CmpInstr, SrcReg, SrcReg2, MRI);
2128
2129 if (SrcReg2 != 0)
2130 return false;
2131
2132 // CmpInstr is a Compare instruction if destination register is not used.
2133 if (!MRI->use_nodbg_empty(CmpInstr.getOperand(0).getReg()))
2134 return false;
2135
2136 if (CmpValue == 0 && substituteCmpToZero(CmpInstr, SrcReg, *MRI))
2137 return true;
2138 return (CmpValue == 0 || CmpValue == 1) &&
2139 removeCmpToZeroOrOne(CmpInstr, SrcReg, CmpValue, *MRI);
2140}
2141
2142/// Get opcode of S version of Instr.
2143/// If Instr is S version its opcode is returned.
2144/// AArch64::INSTRUCTION_LIST_END is returned if Instr does not have S version
2145/// or we are not interested in it.
2146static unsigned sForm(MachineInstr &Instr) {
2147 switch (Instr.getOpcode()) {
2148 default:
2149 return AArch64::INSTRUCTION_LIST_END;
2150
2151 case AArch64::ADDSWrr:
2152 case AArch64::ADDSWri:
2153 case AArch64::ADDSXrr:
2154 case AArch64::ADDSXri:
2155 case AArch64::ADDSWrx:
2156 case AArch64::ADDSXrx:
2157 case AArch64::ADDSWrs:
2158 case AArch64::ADDSXrs:
2159 case AArch64::SUBSWrr:
2160 case AArch64::SUBSWri:
2161 case AArch64::SUBSWrx:
2162 case AArch64::SUBSWrs:
2163 case AArch64::SUBSXrr:
2164 case AArch64::SUBSXri:
2165 case AArch64::SUBSXrx:
2166 case AArch64::SUBSXrs:
2167 case AArch64::ANDSWri:
2168 case AArch64::ANDSWrr:
2169 case AArch64::ANDSWrs:
2170 case AArch64::ANDSXri:
2171 case AArch64::ANDSXrr:
2172 case AArch64::ANDSXrs:
2173 case AArch64::BICSWrr:
2174 case AArch64::BICSXrr:
2175 case AArch64::BICSWrs:
2176 case AArch64::BICSXrs:
2177 case AArch64::ADCSWr:
2178 case AArch64::ADCSXr:
2179 case AArch64::SBCSWr:
2180 case AArch64::SBCSXr:
2181 return Instr.getOpcode();
2182
2183 case AArch64::ADDWrr:
2184 return AArch64::ADDSWrr;
2185 case AArch64::ADDWri:
2186 return AArch64::ADDSWri;
2187 case AArch64::ADDXrr:
2188 return AArch64::ADDSXrr;
2189 case AArch64::ADDXri:
2190 return AArch64::ADDSXri;
2191 case AArch64::ADDWrx:
2192 return AArch64::ADDSWrx;
2193 case AArch64::ADDXrx:
2194 return AArch64::ADDSXrx;
2195 case AArch64::ADDWrs:
2196 return AArch64::ADDSWrs;
2197 case AArch64::ADDXrs:
2198 return AArch64::ADDSXrs;
2199 case AArch64::ADCWr:
2200 return AArch64::ADCSWr;
2201 case AArch64::ADCXr:
2202 return AArch64::ADCSXr;
2203 case AArch64::SUBWrr:
2204 return AArch64::SUBSWrr;
2205 case AArch64::SUBWri:
2206 return AArch64::SUBSWri;
2207 case AArch64::SUBXrr:
2208 return AArch64::SUBSXrr;
2209 case AArch64::SUBXri:
2210 return AArch64::SUBSXri;
2211 case AArch64::SUBWrx:
2212 return AArch64::SUBSWrx;
2213 case AArch64::SUBXrx:
2214 return AArch64::SUBSXrx;
2215 case AArch64::SUBWrs:
2216 return AArch64::SUBSWrs;
2217 case AArch64::SUBXrs:
2218 return AArch64::SUBSXrs;
2219 case AArch64::SBCWr:
2220 return AArch64::SBCSWr;
2221 case AArch64::SBCXr:
2222 return AArch64::SBCSXr;
2223 case AArch64::ANDWri:
2224 return AArch64::ANDSWri;
2225 case AArch64::ANDXri:
2226 return AArch64::ANDSXri;
2227 case AArch64::ANDWrr:
2228 return AArch64::ANDSWrr;
2229 case AArch64::ANDWrs:
2230 return AArch64::ANDSWrs;
2231 case AArch64::ANDXrr:
2232 return AArch64::ANDSXrr;
2233 case AArch64::ANDXrs:
2234 return AArch64::ANDSXrs;
2235 case AArch64::BICWrr:
2236 return AArch64::BICSWrr;
2237 case AArch64::BICXrr:
2238 return AArch64::BICSXrr;
2239 case AArch64::BICWrs:
2240 return AArch64::BICSWrs;
2241 case AArch64::BICXrs:
2242 return AArch64::BICSXrs;
2243 }
2244}
2245
2246/// Check if AArch64::NZCV should be alive in successors of MBB.
2248 for (auto *BB : MBB->successors())
2249 if (BB->isLiveIn(AArch64::NZCV))
2250 return true;
2251 return false;
2252}
2253
2254/// \returns The condition code operand index for \p Instr if it is a branch
2255/// or select and -1 otherwise.
2256int AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(
2257 const MachineInstr &Instr) {
2258 switch (Instr.getOpcode()) {
2259 default:
2260 return -1;
2261
2262 case AArch64::Bcc: {
2263 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV, /*TRI=*/nullptr);
2264 assert(Idx >= 2);
2265 return Idx - 2;
2266 }
2267
2268 case AArch64::CSINVWr:
2269 case AArch64::CSINVXr:
2270 case AArch64::CSINCWr:
2271 case AArch64::CSINCXr:
2272 case AArch64::CSELWr:
2273 case AArch64::CSELXr:
2274 case AArch64::CSNEGWr:
2275 case AArch64::CSNEGXr:
2276 case AArch64::FCSELSrrr:
2277 case AArch64::FCSELDrrr: {
2278 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV, /*TRI=*/nullptr);
2279 assert(Idx >= 1);
2280 return Idx - 1;
2281 }
2282 }
2283}
2284
2285/// Find a condition code used by the instruction.
2286/// Returns AArch64CC::Invalid if either the instruction does not use condition
2287/// codes or we don't optimize CmpInstr in the presence of such instructions.
2289 int CCIdx =
2290 AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(Instr);
2291 return CCIdx >= 0 ? static_cast<AArch64CC::CondCode>(
2292 Instr.getOperand(CCIdx).getImm())
2294}
2295
2298 UsedNZCV UsedFlags;
2299 switch (CC) {
2300 default:
2301 break;
2302
2303 case AArch64CC::EQ: // Z set
2304 case AArch64CC::NE: // Z clear
2305 UsedFlags.Z = true;
2306 break;
2307
2308 case AArch64CC::HI: // Z clear and C set
2309 case AArch64CC::LS: // Z set or C clear
2310 UsedFlags.Z = true;
2311 [[fallthrough]];
2312 case AArch64CC::HS: // C set
2313 case AArch64CC::LO: // C clear
2314 UsedFlags.C = true;
2315 break;
2316
2317 case AArch64CC::MI: // N set
2318 case AArch64CC::PL: // N clear
2319 UsedFlags.N = true;
2320 break;
2321
2322 case AArch64CC::VS: // V set
2323 case AArch64CC::VC: // V clear
2324 UsedFlags.V = true;
2325 break;
2326
2327 case AArch64CC::GT: // Z clear, N and V the same
2328 case AArch64CC::LE: // Z set, N and V differ
2329 UsedFlags.Z = true;
2330 [[fallthrough]];
2331 case AArch64CC::GE: // N and V the same
2332 case AArch64CC::LT: // N and V differ
2333 UsedFlags.N = true;
2334 UsedFlags.V = true;
2335 break;
2336 }
2337 return UsedFlags;
2338}
2339
2340/// \returns Conditions flags used after \p CmpInstr in its MachineBB if NZCV
2341/// flags are not alive in successors of the same \p CmpInstr and \p MI parent.
2342/// \returns std::nullopt otherwise.
2343///
2344/// Collect instructions using that flags in \p CCUseInstrs if provided.
2345std::optional<UsedNZCV>
2347 const TargetRegisterInfo &TRI,
2348 SmallVectorImpl<MachineInstr *> *CCUseInstrs) {
2349 MachineBasicBlock *CmpParent = CmpInstr.getParent();
2350 if (MI.getParent() != CmpParent)
2351 return std::nullopt;
2352
2353 if (areCFlagsAliveInSuccessors(CmpParent))
2354 return std::nullopt;
2355
2356 UsedNZCV NZCVUsedAfterCmp;
2358 std::next(CmpInstr.getIterator()), CmpParent->instr_end())) {
2359 if (Instr.readsRegister(AArch64::NZCV, &TRI)) {
2361 if (CC == AArch64CC::Invalid) // Unsupported conditional instruction
2362 return std::nullopt;
2363 NZCVUsedAfterCmp |= getUsedNZCV(CC);
2364 if (CCUseInstrs)
2365 CCUseInstrs->push_back(&Instr);
2366 }
2367 if (Instr.modifiesRegister(AArch64::NZCV, &TRI))
2368 break;
2369 }
2370 return NZCVUsedAfterCmp;
2371}
2372
2373static bool isADDSRegImm(unsigned Opcode) {
2374 return Opcode == AArch64::ADDSWri || Opcode == AArch64::ADDSXri;
2375}
2376
2377static bool isSUBSRegImm(unsigned Opcode) {
2378 return Opcode == AArch64::SUBSWri || Opcode == AArch64::SUBSXri;
2379}
2380
2382 unsigned Opc = sForm(MI);
2383 switch (Opc) {
2384 case AArch64::ANDSWri:
2385 case AArch64::ANDSWrr:
2386 case AArch64::ANDSWrs:
2387 case AArch64::ANDSXri:
2388 case AArch64::ANDSXrr:
2389 case AArch64::ANDSXrs:
2390 case AArch64::BICSWrr:
2391 case AArch64::BICSXrr:
2392 case AArch64::BICSWrs:
2393 case AArch64::BICSXrs:
2394 return true;
2395 default:
2396 return false;
2397 }
2398}
2399
2400/// Check if CmpInstr can be substituted by MI.
2401///
2402/// CmpInstr can be substituted:
2403/// - CmpInstr is either 'ADDS %vreg, 0' or 'SUBS %vreg, 0'
2404/// - and, MI and CmpInstr are from the same MachineBB
2405/// - and, condition flags are not alive in successors of the CmpInstr parent
2406/// - and, if MI opcode is the S form there must be no defs of flags between
2407/// MI and CmpInstr
2408/// or if MI opcode is not the S form there must be neither defs of flags
2409/// nor uses of flags between MI and CmpInstr.
2410/// - and, C is not used after CmpInstr; CmpInstr's C is from adds/subs #0 on
2411/// SrcReg and can differ from MI (e.g. carry out of ADCS/SBCS).
2412/// - and, V is not used after CmpInstr unless MI is AND/BIC (V cleared) or MI
2413/// has NoSWrap (overflow is poison and the fold is still safe).
2415 const TargetRegisterInfo &TRI) {
2416 // MI is an opcode sForm maps (add/sub/adc/sbc/and/bic and their S forms).
2417 assert(sForm(MI) != AArch64::INSTRUCTION_LIST_END);
2418
2419 const unsigned CmpOpcode = CmpInstr.getOpcode();
2420 if (!isADDSRegImm(CmpOpcode) && !isSUBSRegImm(CmpOpcode))
2421 return false;
2422
2423 assert((CmpInstr.getOperand(2).isImm() &&
2424 CmpInstr.getOperand(2).getImm() == 0) &&
2425 "Caller guarantees that CmpInstr compares with constant 0");
2426
2427 std::optional<UsedNZCV> NZVCUsed = examineCFlagsUse(MI, CmpInstr, TRI);
2428 if (!NZVCUsed || NZVCUsed->C)
2429 return false;
2430
2431 // CmpInstr is ADDS/SUBS with immediate 0 on SrcReg (compare SrcReg to zero).
2432 // After the fold, users see NZCV from MI (or its S form), not from CmpInstr.
2433 // N/Z match CmpInstr for the value in SrcReg; C/V need not match in general
2434 // (e.g. ADCS vs adds #0), so we require C unused after CmpInstr and gate V
2435 // as below. NoSWrap makes signed overflow poison; AND/BIC clear V.
2436 if (NZVCUsed->V && !MI.getFlag(MachineInstr::NoSWrap) && !isANDOpcode(MI))
2437 return false;
2438
2439 AccessKind AccessToCheck = AK_Write;
2440 if (sForm(MI) != MI.getOpcode())
2441 AccessToCheck = AK_All;
2442 return !areCFlagsAccessedBetweenInstrs(&MI, &CmpInstr, &TRI, AccessToCheck);
2443}
2444
2445/// Substitute an instruction comparing to zero with another instruction
2446/// which produces needed condition flags.
2447///
2448/// Return true on success.
2449bool AArch64InstrInfo::substituteCmpToZero(
2450 MachineInstr &CmpInstr, unsigned SrcReg,
2451 const MachineRegisterInfo &MRI) const {
2452 // Get the unique definition of SrcReg.
2453 MachineInstr *MI = MRI.getUniqueVRegDef(SrcReg);
2454 if (!MI)
2455 return false;
2456
2457 const TargetRegisterInfo &TRI = getRegisterInfo();
2458
2459 unsigned NewOpc = sForm(*MI);
2460 if (NewOpc == AArch64::INSTRUCTION_LIST_END)
2461 return false;
2462
2463 if (!canInstrSubstituteCmpInstr(*MI, CmpInstr, TRI))
2464 return false;
2465
2466 // Update the instruction to set NZCV.
2467 MI->setDesc(get(NewOpc));
2468 CmpInstr.eraseFromParent();
2470 (void)succeeded;
2471 assert(succeeded && "Some operands reg class are incompatible!");
2472 MI->addRegisterDefined(AArch64::NZCV, &TRI);
2473 return true;
2474}
2475
2476/// \returns True if \p CmpInstr can be removed.
2477///
2478/// \p IsInvertCC is true if, after removing \p CmpInstr, condition
2479/// codes used in \p CCUseInstrs must be inverted.
2481 int CmpValue, const TargetRegisterInfo &TRI,
2483 bool &IsInvertCC) {
2484 assert((CmpValue == 0 || CmpValue == 1) &&
2485 "Only comparisons to 0 or 1 considered for removal!");
2486
2487 // MI is 'CSINCWr %vreg, wzr, wzr, <cc>' or 'CSINCXr %vreg, xzr, xzr, <cc>'
2488 unsigned MIOpc = MI.getOpcode();
2489 if (MIOpc == AArch64::CSINCWr) {
2490 if (MI.getOperand(1).getReg() != AArch64::WZR ||
2491 MI.getOperand(2).getReg() != AArch64::WZR)
2492 return false;
2493 } else if (MIOpc == AArch64::CSINCXr) {
2494 if (MI.getOperand(1).getReg() != AArch64::XZR ||
2495 MI.getOperand(2).getReg() != AArch64::XZR)
2496 return false;
2497 } else {
2498 return false;
2499 }
2501 if (MICC == AArch64CC::Invalid)
2502 return false;
2503
2504 // NZCV needs to be defined
2505 if (MI.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) != -1)
2506 return false;
2507
2508 // CmpInstr is 'ADDS %vreg, 0' or 'SUBS %vreg, 0' or 'SUBS %vreg, 1'
2509 const unsigned CmpOpcode = CmpInstr.getOpcode();
2510 bool IsSubsRegImm = isSUBSRegImm(CmpOpcode);
2511 if (CmpValue && !IsSubsRegImm)
2512 return false;
2513 if (!CmpValue && !IsSubsRegImm && !isADDSRegImm(CmpOpcode))
2514 return false;
2515
2516 // MI conditions allowed: eq, ne, mi, pl
2517 UsedNZCV MIUsedNZCV = getUsedNZCV(MICC);
2518 if (MIUsedNZCV.C || MIUsedNZCV.V)
2519 return false;
2520
2521 std::optional<UsedNZCV> NZCVUsedAfterCmp =
2522 examineCFlagsUse(MI, CmpInstr, TRI, &CCUseInstrs);
2523 // Condition flags are not used in CmpInstr basic block successors and only
2524 // Z or N flags allowed to be used after CmpInstr within its basic block
2525 if (!NZCVUsedAfterCmp || NZCVUsedAfterCmp->C || NZCVUsedAfterCmp->V)
2526 return false;
2527 // Z or N flag used after CmpInstr must correspond to the flag used in MI
2528 if ((MIUsedNZCV.Z && NZCVUsedAfterCmp->N) ||
2529 (MIUsedNZCV.N && NZCVUsedAfterCmp->Z))
2530 return false;
2531 // If CmpInstr is comparison to zero MI conditions are limited to eq, ne
2532 if (MIUsedNZCV.N && !CmpValue)
2533 return false;
2534
2535 // There must be no defs of flags between MI and CmpInstr
2536 if (areCFlagsAccessedBetweenInstrs(&MI, &CmpInstr, &TRI, AK_Write))
2537 return false;
2538
2539 // Condition code is inverted in the following cases:
2540 // 1. MI condition is ne; CmpInstr is 'ADDS %vreg, 0' or 'SUBS %vreg, 0'
2541 // 2. MI condition is eq, pl; CmpInstr is 'SUBS %vreg, 1'
2542 IsInvertCC = (CmpValue && (MICC == AArch64CC::EQ || MICC == AArch64CC::PL)) ||
2543 (!CmpValue && MICC == AArch64CC::NE);
2544 return true;
2545}
2546
2547/// Remove comparison in csinc-cmp sequence
2548///
2549/// Examples:
2550/// 1. \code
2551/// csinc w9, wzr, wzr, ne
2552/// cmp w9, #0
2553/// b.eq
2554/// \endcode
2555/// to
2556/// \code
2557/// csinc w9, wzr, wzr, ne
2558/// b.ne
2559/// \endcode
2560///
2561/// 2. \code
2562/// csinc x2, xzr, xzr, mi
2563/// cmp x2, #1
2564/// b.pl
2565/// \endcode
2566/// to
2567/// \code
2568/// csinc x2, xzr, xzr, mi
2569/// b.pl
2570/// \endcode
2571///
2572/// \param CmpInstr comparison instruction
2573/// \return True when comparison removed
2574bool AArch64InstrInfo::removeCmpToZeroOrOne(
2575 MachineInstr &CmpInstr, unsigned SrcReg, int CmpValue,
2576 const MachineRegisterInfo &MRI) const {
2577 MachineInstr *MI = MRI.getUniqueVRegDef(SrcReg);
2578 if (!MI)
2579 return false;
2580 const TargetRegisterInfo &TRI = getRegisterInfo();
2581 SmallVector<MachineInstr *, 4> CCUseInstrs;
2582 bool IsInvertCC = false;
2583 if (!canCmpInstrBeRemoved(*MI, CmpInstr, CmpValue, TRI, CCUseInstrs,
2584 IsInvertCC))
2585 return false;
2586 // Make transformation
2587 CmpInstr.eraseFromParent();
2588 if (IsInvertCC) {
2589 // Invert condition codes in CmpInstr CC users
2590 for (MachineInstr *CCUseInstr : CCUseInstrs) {
2591 int Idx = findCondCodeUseOperandIdxForBranchOrSelect(*CCUseInstr);
2592 assert(Idx >= 0 && "Unexpected instruction using CC.");
2593 MachineOperand &CCOperand = CCUseInstr->getOperand(Idx);
2595 static_cast<AArch64CC::CondCode>(CCOperand.getImm()));
2596 CCOperand.setImm(CCUse);
2597 }
2598 }
2599 return true;
2600}
2601
2602bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
2603 if (MI.getOpcode() != TargetOpcode::LOAD_STACK_GUARD &&
2604 MI.getOpcode() != AArch64::CATCHRET &&
2605 MI.getOpcode() != AArch64::STACK_GUARD_UNMIX)
2606 return false;
2607
2608 MachineBasicBlock &MBB = *MI.getParent();
2609 auto &Subtarget = MBB.getParent()->getSubtarget<AArch64Subtarget>();
2610 auto TRI = Subtarget.getRegisterInfo();
2611 DebugLoc DL = MI.getDebugLoc();
2612
2613 if (MI.getOpcode() == AArch64::STACK_GUARD_UNMIX) {
2614 // Expand STACK_GUARD_UNMIX to: sub Rd, fp, Rs
2615 // This computes FP - stored_mixed_value to unmix the cookie
2616 Register DstReg = MI.getOperand(0).getReg();
2617 Register SrcReg = MI.getOperand(1).getReg();
2618
2619 BuildMI(MBB, MI, DL, get(AArch64::SUBXrr), DstReg)
2620 .addReg(AArch64::FP)
2621 .addReg(SrcReg);
2622
2623 MBB.erase(MI);
2624 return true;
2625 }
2626
2627 if (MI.getOpcode() == AArch64::CATCHRET) {
2628 // Skip to the first instruction before the epilog.
2629 const TargetInstrInfo *TII =
2631 MachineBasicBlock *TargetMBB = MI.getOperand(0).getMBB();
2633 MachineBasicBlock::iterator FirstEpilogSEH = std::prev(MBBI);
2634 while (FirstEpilogSEH->getFlag(MachineInstr::FrameDestroy) &&
2635 FirstEpilogSEH != MBB.begin())
2636 FirstEpilogSEH = std::prev(FirstEpilogSEH);
2637 if (FirstEpilogSEH != MBB.begin())
2638 FirstEpilogSEH = std::next(FirstEpilogSEH);
2639 BuildMI(MBB, FirstEpilogSEH, DL, TII->get(AArch64::ADRP))
2640 .addReg(AArch64::X0, RegState::Define)
2641 .addMBB(TargetMBB, AArch64II::MO_PAGE);
2642 BuildMI(MBB, FirstEpilogSEH, DL, TII->get(AArch64::ADDXri))
2643 .addReg(AArch64::X0, RegState::Define)
2644 .addReg(AArch64::X0)
2646 .addImm(0);
2647 TargetMBB->setMachineBlockAddressTaken();
2648 return true;
2649 }
2650
2651 Register Reg = MI.getOperand(0).getReg();
2653 if (M.getStackProtectorGuard() == "sysreg") {
2654 const AArch64SysReg::SysReg *SrcReg =
2655 AArch64SysReg::lookupSysRegByName(M.getStackProtectorGuardReg());
2656 if (!SrcReg)
2657 report_fatal_error("Unknown SysReg for Stack Protector Guard Register");
2658
2659 // mrs xN, sysreg
2660 BuildMI(MBB, MI, DL, get(AArch64::MRS))
2662 .addImm(SrcReg->Encoding);
2663 int Offset = M.getStackProtectorGuardOffset();
2664 if (Offset >= 0 && Offset <= 32760 && Offset % 8 == 0) {
2665 // ldr xN, [xN, #offset]
2666 BuildMI(MBB, MI, DL, get(AArch64::LDRXui))
2667 .addDef(Reg)
2669 .addImm(Offset / 8);
2670 } else if (Offset >= -256 && Offset <= 255) {
2671 // ldur xN, [xN, #offset]
2672 BuildMI(MBB, MI, DL, get(AArch64::LDURXi))
2673 .addDef(Reg)
2675 .addImm(Offset);
2676 } else if (Offset >= -4095 && Offset <= 4095) {
2677 if (Offset > 0) {
2678 // add xN, xN, #offset
2679 BuildMI(MBB, MI, DL, get(AArch64::ADDXri))
2680 .addDef(Reg)
2682 .addImm(Offset)
2683 .addImm(0);
2684 } else {
2685 // sub xN, xN, #offset
2686 BuildMI(MBB, MI, DL, get(AArch64::SUBXri))
2687 .addDef(Reg)
2689 .addImm(-Offset)
2690 .addImm(0);
2691 }
2692 // ldr xN, [xN]
2693 BuildMI(MBB, MI, DL, get(AArch64::LDRXui))
2694 .addDef(Reg)
2696 .addImm(0);
2697 } else {
2698 // Cases that are larger than +/- 4095 and not a multiple of 8, or larger
2699 // than 23760.
2700 // It might be nice to use AArch64::MOVi32imm here, which would get
2701 // expanded in PreSched2 after PostRA, but our lone scratch Reg already
2702 // contains the MRS result. findScratchNonCalleeSaveRegister() in
2703 // AArch64FrameLowering might help us find such a scratch register
2704 // though. If we failed to find a scratch register, we could emit a
2705 // stream of add instructions to build up the immediate. Or, we could try
2706 // to insert a AArch64::MOVi32imm before register allocation so that we
2707 // didn't need to scavenge for a scratch register.
2708 report_fatal_error("Unable to encode Stack Protector Guard Offset");
2709 }
2710 MBB.erase(MI);
2711 return true;
2712 }
2713
2714 const GlobalValue *GV =
2715 cast<GlobalValue>((*MI.memoperands_begin())->getValue());
2716 const TargetMachine &TM = MBB.getParent()->getTarget();
2717 unsigned OpFlags = Subtarget.ClassifyGlobalReference(GV, TM);
2718 const unsigned char MO_NC = AArch64II::MO_NC;
2719
2720 unsigned GuardWidth = M.getStackProtectorGuardValueWidth().value_or(
2721 Subtarget.isTargetILP32() ? 4 : 8);
2722 if (GuardWidth != 4 && GuardWidth != 8)
2723 report_fatal_error("Unsupported stack protector value width");
2724 if ((OpFlags & AArch64II::MO_GOT) != 0) {
2725 BuildMI(MBB, MI, DL, get(AArch64::LOADgot), Reg)
2726 .addGlobalAddress(GV, 0, OpFlags);
2727 if (GuardWidth == 4) {
2728 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2729 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2730 .addDef(Reg32, RegState::Dead)
2732 .addImm(0)
2733 .addMemOperand(*MI.memoperands_begin())
2735 } else {
2736 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2738 .addImm(0)
2739 .addMemOperand(*MI.memoperands_begin());
2740 }
2741 } else if (TM.getCodeModel() == CodeModel::Large) {
2742 BuildMI(MBB, MI, DL, get(AArch64::MOVZXi), Reg)
2743 .addGlobalAddress(GV, 0, AArch64II::MO_G0 | MO_NC)
2744 .addImm(0);
2745 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2747 .addGlobalAddress(GV, 0, AArch64II::MO_G1 | MO_NC)
2748 .addImm(16);
2749 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2751 .addGlobalAddress(GV, 0, AArch64II::MO_G2 | MO_NC)
2752 .addImm(32);
2753 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2756 .addImm(48);
2757 if (GuardWidth == 4) {
2758 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2759 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2760 .addDef(Reg32, RegState::Dead)
2762 .addImm(0)
2763 .addMemOperand(*MI.memoperands_begin())
2765 } else {
2766 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2768 .addImm(0)
2769 .addMemOperand(*MI.memoperands_begin());
2770 }
2771 } else {
2772 BuildMI(MBB, MI, DL, get(AArch64::ADRP), Reg)
2773 .addGlobalAddress(GV, 0, OpFlags | AArch64II::MO_PAGE);
2774 unsigned char LoFlags = OpFlags | AArch64II::MO_PAGEOFF | MO_NC;
2775 if (GuardWidth == 4) {
2776 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2777 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2778 .addDef(Reg32, RegState::Dead)
2780 .addGlobalAddress(GV, 0, LoFlags)
2781 .addMemOperand(*MI.memoperands_begin())
2783 } else {
2784 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2786 .addGlobalAddress(GV, 0, LoFlags)
2787 .addMemOperand(*MI.memoperands_begin());
2788 }
2789 }
2790 // To match MSVC. Unlike x86_64 which uses xor instruction to mix the cookie,
2791 // we use sub instruction to mix the cookie on aarch64.
2792 // The mixing happens here in expandPostRAPseudo (after RA) to ensure we use
2793 // the final frame pointer value.
2794 if (Subtarget.getTargetTriple().isOSMSVCRT())
2795 BuildMI(MBB, MI, DL, get(AArch64::SUBXrr), Reg)
2796 .addReg(AArch64::FP)
2798
2799 MBB.erase(MI);
2800
2801 return true;
2802}
2803
2804// Return true if this instruction simply sets its single destination register
2805// to zero. This is equivalent to a register rename of the zero-register.
2807 switch (MI.getOpcode()) {
2808 default:
2809 break;
2810 case AArch64::MOVZWi:
2811 case AArch64::MOVZXi: // movz Rd, #0 (LSL #0)
2812 if (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) {
2813 assert(MI.getDesc().getNumOperands() == 3 &&
2814 MI.getOperand(2).getImm() == 0 && "invalid MOVZi operands");
2815 return true;
2816 }
2817 break;
2818 case AArch64::ANDWri: // and Rd, Rzr, #imm
2819 return MI.getOperand(1).getReg() == AArch64::WZR;
2820 case AArch64::ANDXri:
2821 return MI.getOperand(1).getReg() == AArch64::XZR;
2822 case TargetOpcode::COPY:
2823 return MI.getOperand(1).getReg() == AArch64::WZR;
2824 }
2825 return false;
2826}
2827
2828// Return true if this instruction simply renames a general register without
2829// modifying bits.
2831 switch (MI.getOpcode()) {
2832 default:
2833 break;
2834 case TargetOpcode::COPY: {
2835 // GPR32 copies will by lowered to ORRXrs
2836 Register DstReg = MI.getOperand(0).getReg();
2837 return (AArch64::GPR32RegClass.contains(DstReg) ||
2838 AArch64::GPR64RegClass.contains(DstReg));
2839 }
2840 case AArch64::ORRXrs: // orr Xd, Xzr, Xm (LSL #0)
2841 if (MI.getOperand(1).getReg() == AArch64::XZR) {
2842 assert(MI.getDesc().getNumOperands() == 4 &&
2843 MI.getOperand(3).getImm() == 0 && "invalid ORRrs operands");
2844 return true;
2845 }
2846 break;
2847 case AArch64::ADDXri: // add Xd, Xn, #0 (LSL #0)
2848 if (MI.getOperand(2).getImm() == 0) {
2849 assert(MI.getDesc().getNumOperands() == 4 &&
2850 MI.getOperand(3).getImm() == 0 && "invalid ADDXri operands");
2851 return true;
2852 }
2853 break;
2854 }
2855 return false;
2856}
2857
2858// Return true if this instruction simply renames a general register without
2859// modifying bits.
2861 switch (MI.getOpcode()) {
2862 default:
2863 break;
2864 case TargetOpcode::COPY: {
2865 Register DstReg = MI.getOperand(0).getReg();
2866 return AArch64::FPR128RegClass.contains(DstReg);
2867 }
2868 case AArch64::ORRv16i8:
2869 if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
2870 assert(MI.getDesc().getNumOperands() == 3 && MI.getOperand(0).isReg() &&
2871 "invalid ORRv16i8 operands");
2872 return true;
2873 }
2874 break;
2875 }
2876 return false;
2877}
2878
2879static bool isFrameLoadOpcode(int Opcode) {
2880 switch (Opcode) {
2881 default:
2882 return false;
2883 case AArch64::LDRWui:
2884 case AArch64::LDRXui:
2885 case AArch64::LDRBui:
2886 case AArch64::LDRHui:
2887 case AArch64::LDRSui:
2888 case AArch64::LDRDui:
2889 case AArch64::LDRQui:
2890 case AArch64::LDR_PXI:
2891 return true;
2892 }
2893}
2894
2896 int &FrameIndex) const {
2897 if (!isFrameLoadOpcode(MI.getOpcode()))
2898 return Register();
2899
2900 if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
2901 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
2902 FrameIndex = MI.getOperand(1).getIndex();
2903 return MI.getOperand(0).getReg();
2904 }
2905 return Register();
2906}
2907
2908static bool isFrameStoreOpcode(int Opcode) {
2909 switch (Opcode) {
2910 default:
2911 return false;
2912 case AArch64::STRWui:
2913 case AArch64::STRXui:
2914 case AArch64::STRBui:
2915 case AArch64::STRHui:
2916 case AArch64::STRSui:
2917 case AArch64::STRDui:
2918 case AArch64::STRQui:
2919 case AArch64::STR_PXI:
2920 return true;
2921 }
2922}
2923
2925 int &FrameIndex) const {
2926 if (!isFrameStoreOpcode(MI.getOpcode()))
2927 return Register();
2928
2929 if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
2930 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
2931 FrameIndex = MI.getOperand(1).getIndex();
2932 return MI.getOperand(0).getReg();
2933 }
2934 return Register();
2935}
2936
2938 int &FrameIndex) const {
2939 if (!isFrameStoreOpcode(MI.getOpcode()))
2940 return Register();
2941
2942 if (Register Reg = isStoreToStackSlot(MI, FrameIndex))
2943 return Reg;
2944
2946 if (hasStoreToStackSlot(MI, Accesses)) {
2947 if (Accesses.size() > 1)
2948 return Register();
2949
2950 FrameIndex =
2951 cast<FixedStackPseudoSourceValue>(Accesses.front()->getPseudoValue())
2952 ->getFrameIndex();
2953 return MI.getOperand(0).getReg();
2954 }
2955 return Register();
2956}
2957
2959 int &FrameIndex) const {
2960 if (!isFrameLoadOpcode(MI.getOpcode()))
2961 return Register();
2962
2963 if (Register Reg = isLoadFromStackSlot(MI, FrameIndex))
2964 return Reg;
2965
2967 if (hasLoadFromStackSlot(MI, Accesses)) {
2968 if (Accesses.size() > 1)
2969 return Register();
2970
2971 FrameIndex =
2972 cast<FixedStackPseudoSourceValue>(Accesses.front()->getPseudoValue())
2973 ->getFrameIndex();
2974 return MI.getOperand(0).getReg();
2975 }
2976 return Register();
2977}
2978
2979/// Check all MachineMemOperands for a hint to suppress pairing.
2981 return llvm::any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
2982 return MMO->getFlags() & MOSuppressPair;
2983 });
2984}
2985
2986/// Set a flag on the first MachineMemOperand to suppress pairing.
2988 if (MI.memoperands_empty())
2989 return;
2990 (*MI.memoperands_begin())->setFlags(MOSuppressPair);
2991}
2992
2993/// Check all MachineMemOperands for a hint that the load/store is strided.
2995 return llvm::any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
2996 return MMO->getFlags() & MOStridedAccess;
2997 });
2998}
2999
3001 switch (Opc) {
3002 default:
3003 return false;
3004 case AArch64::STURSi:
3005 case AArch64::STRSpre:
3006 case AArch64::STURDi:
3007 case AArch64::STRDpre:
3008 case AArch64::STURQi:
3009 case AArch64::STRQpre:
3010 case AArch64::STURBBi:
3011 case AArch64::STURHHi:
3012 case AArch64::STURWi:
3013 case AArch64::STRWpre:
3014 case AArch64::STURXi:
3015 case AArch64::STRXpre:
3016 case AArch64::LDURSi:
3017 case AArch64::LDRSpre:
3018 case AArch64::LDURDi:
3019 case AArch64::LDRDpre:
3020 case AArch64::LDURQi:
3021 case AArch64::LDRQpre:
3022 case AArch64::LDURWi:
3023 case AArch64::LDRWpre:
3024 case AArch64::LDURXi:
3025 case AArch64::LDRXpre:
3026 case AArch64::LDRSWpre:
3027 case AArch64::LDURSWi:
3028 case AArch64::LDURHHi:
3029 case AArch64::LDURBBi:
3030 case AArch64::LDURSBWi:
3031 case AArch64::LDURSHWi:
3032 return true;
3033 }
3034}
3035
3036std::optional<unsigned> AArch64InstrInfo::getUnscaledLdSt(unsigned Opc) {
3037 switch (Opc) {
3038 default: return {};
3039 case AArch64::PRFMui: return AArch64::PRFUMi;
3040 case AArch64::LDRXui: return AArch64::LDURXi;
3041 case AArch64::LDRWui: return AArch64::LDURWi;
3042 case AArch64::LDRBui: return AArch64::LDURBi;
3043 case AArch64::LDRHui: return AArch64::LDURHi;
3044 case AArch64::LDRSui: return AArch64::LDURSi;
3045 case AArch64::LDRDui: return AArch64::LDURDi;
3046 case AArch64::LDRQui: return AArch64::LDURQi;
3047 case AArch64::LDRBBui: return AArch64::LDURBBi;
3048 case AArch64::LDRHHui: return AArch64::LDURHHi;
3049 case AArch64::LDRSBXui: return AArch64::LDURSBXi;
3050 case AArch64::LDRSBWui: return AArch64::LDURSBWi;
3051 case AArch64::LDRSHXui: return AArch64::LDURSHXi;
3052 case AArch64::LDRSHWui: return AArch64::LDURSHWi;
3053 case AArch64::LDRSWui: return AArch64::LDURSWi;
3054 case AArch64::STRXui: return AArch64::STURXi;
3055 case AArch64::STRWui: return AArch64::STURWi;
3056 case AArch64::STRBui: return AArch64::STURBi;
3057 case AArch64::STRHui: return AArch64::STURHi;
3058 case AArch64::STRSui: return AArch64::STURSi;
3059 case AArch64::STRDui: return AArch64::STURDi;
3060 case AArch64::STRQui: return AArch64::STURQi;
3061 case AArch64::STRBBui: return AArch64::STURBBi;
3062 case AArch64::STRHHui: return AArch64::STURHHi;
3063 }
3064}
3065
3067 switch (Opc) {
3068 default:
3069 llvm_unreachable("Unhandled Opcode in getLoadStoreImmIdx");
3070 case AArch64::ADDG:
3071 case AArch64::LDAPURBi:
3072 case AArch64::LDAPURHi:
3073 case AArch64::LDAPURi:
3074 case AArch64::LDAPURSBWi:
3075 case AArch64::LDAPURSBXi:
3076 case AArch64::LDAPURSHWi:
3077 case AArch64::LDAPURSHXi:
3078 case AArch64::LDAPURSWi:
3079 case AArch64::LDAPURXi:
3080 case AArch64::LDR_PPXI:
3081 case AArch64::LDR_PXI:
3082 case AArch64::LDR_ZXI:
3083 case AArch64::LDR_ZZXI:
3084 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
3085 case AArch64::LDR_ZZZXI:
3086 case AArch64::LDR_ZZZZXI:
3087 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
3088 case AArch64::LDRBBui:
3089 case AArch64::LDRBui:
3090 case AArch64::LDRDui:
3091 case AArch64::LDRHHui:
3092 case AArch64::LDRHui:
3093 case AArch64::LDRQui:
3094 case AArch64::LDRSBWui:
3095 case AArch64::LDRSBXui:
3096 case AArch64::LDRSHWui:
3097 case AArch64::LDRSHXui:
3098 case AArch64::LDRSui:
3099 case AArch64::LDRSWui:
3100 case AArch64::LDRWui:
3101 case AArch64::LDRXui:
3102 case AArch64::LDURBBi:
3103 case AArch64::LDURBi:
3104 case AArch64::LDURDi:
3105 case AArch64::LDURHHi:
3106 case AArch64::LDURHi:
3107 case AArch64::LDURQi:
3108 case AArch64::LDURSBWi:
3109 case AArch64::LDURSBXi:
3110 case AArch64::LDURSHWi:
3111 case AArch64::LDURSHXi:
3112 case AArch64::LDURSi:
3113 case AArch64::LDURSWi:
3114 case AArch64::LDURWi:
3115 case AArch64::LDURXi:
3116 case AArch64::PRFMui:
3117 case AArch64::PRFUMi:
3118 case AArch64::ST2Gi:
3119 case AArch64::STGi:
3120 case AArch64::STLURBi:
3121 case AArch64::STLURHi:
3122 case AArch64::STLURWi:
3123 case AArch64::STLURXi:
3124 case AArch64::StoreSwiftAsyncContext:
3125 case AArch64::STR_PPXI:
3126 case AArch64::STR_PXI:
3127 case AArch64::STR_ZXI:
3128 case AArch64::STR_ZZXI:
3129 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
3130 case AArch64::STR_ZZZXI:
3131 case AArch64::STR_ZZZZXI:
3132 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
3133 case AArch64::STRBBui:
3134 case AArch64::STRBui:
3135 case AArch64::STRDui:
3136 case AArch64::STRHHui:
3137 case AArch64::STRHui:
3138 case AArch64::STRQui:
3139 case AArch64::STRSui:
3140 case AArch64::STRWui:
3141 case AArch64::STRXui:
3142 case AArch64::STURBBi:
3143 case AArch64::STURBi:
3144 case AArch64::STURDi:
3145 case AArch64::STURHHi:
3146 case AArch64::STURHi:
3147 case AArch64::STURQi:
3148 case AArch64::STURSi:
3149 case AArch64::STURWi:
3150 case AArch64::STURXi:
3151 case AArch64::STZ2Gi:
3152 case AArch64::STZGi:
3153 case AArch64::TAGPstack:
3154 case AArch64::ATOMIC_STORE_HINT_Bi:
3155 case AArch64::ATOMIC_STORE_HINT_Hi:
3156 case AArch64::ATOMIC_STORE_HINT_Wi:
3157 case AArch64::ATOMIC_STORE_HINT_Si:
3158 case AArch64::ATOMIC_STORE_HINT_Xi:
3159 case AArch64::ATOMIC_STORE_HINT_Di:
3160 case AArch64::ATOMIC_STORE_HINT_Bui:
3161 case AArch64::ATOMIC_STORE_HINT_Hui:
3162 case AArch64::ATOMIC_STORE_HINT_Wui:
3163 case AArch64::ATOMIC_STORE_HINT_Sui:
3164 case AArch64::ATOMIC_STORE_HINT_Xui:
3165 case AArch64::ATOMIC_STORE_HINT_Dui:
3166 return 2;
3167 case AArch64::LD1B_D_IMM:
3168 case AArch64::LD1B_H_IMM:
3169 case AArch64::LD1B_IMM:
3170 case AArch64::LD1B_S_IMM:
3171 case AArch64::LD1D_IMM:
3172 case AArch64::LD1H_D_IMM:
3173 case AArch64::LD1H_IMM:
3174 case AArch64::LD1H_S_IMM:
3175 case AArch64::LD1RB_D_IMM:
3176 case AArch64::LD1RB_H_IMM:
3177 case AArch64::LD1RB_IMM:
3178 case AArch64::LD1RB_S_IMM:
3179 case AArch64::LD1RD_IMM:
3180 case AArch64::LD1RH_D_IMM:
3181 case AArch64::LD1RH_IMM:
3182 case AArch64::LD1RH_S_IMM:
3183 case AArch64::LD1RSB_D_IMM:
3184 case AArch64::LD1RSB_H_IMM:
3185 case AArch64::LD1RSB_S_IMM:
3186 case AArch64::LD1RSH_D_IMM:
3187 case AArch64::LD1RSH_S_IMM:
3188 case AArch64::LD1RSW_IMM:
3189 case AArch64::LD1RW_D_IMM:
3190 case AArch64::LD1RW_IMM:
3191 case AArch64::LD1SB_D_IMM:
3192 case AArch64::LD1SB_H_IMM:
3193 case AArch64::LD1SB_S_IMM:
3194 case AArch64::LD1SH_D_IMM:
3195 case AArch64::LD1SH_S_IMM:
3196 case AArch64::LD1SW_D_IMM:
3197 case AArch64::LD1W_D_IMM:
3198 case AArch64::LD1W_IMM:
3199 case AArch64::LD2B_IMM:
3200 case AArch64::LD2D_IMM:
3201 case AArch64::LD2H_IMM:
3202 case AArch64::LD2W_IMM:
3203 case AArch64::LD3B_IMM:
3204 case AArch64::LD3D_IMM:
3205 case AArch64::LD3H_IMM:
3206 case AArch64::LD3W_IMM:
3207 case AArch64::LD4B_IMM:
3208 case AArch64::LD4D_IMM:
3209 case AArch64::LD4H_IMM:
3210 case AArch64::LD4W_IMM:
3211 case AArch64::LDG:
3212 case AArch64::LDNF1B_D_IMM:
3213 case AArch64::LDNF1B_H_IMM:
3214 case AArch64::LDNF1B_IMM:
3215 case AArch64::LDNF1B_S_IMM:
3216 case AArch64::LDNF1D_IMM:
3217 case AArch64::LDNF1H_D_IMM:
3218 case AArch64::LDNF1H_IMM:
3219 case AArch64::LDNF1H_S_IMM:
3220 case AArch64::LDNF1SB_D_IMM:
3221 case AArch64::LDNF1SB_H_IMM:
3222 case AArch64::LDNF1SB_S_IMM:
3223 case AArch64::LDNF1SH_D_IMM:
3224 case AArch64::LDNF1SH_S_IMM:
3225 case AArch64::LDNF1SW_D_IMM:
3226 case AArch64::LDNF1W_D_IMM:
3227 case AArch64::LDNF1W_IMM:
3228 case AArch64::LDNPDi:
3229 case AArch64::LDNPQi:
3230 case AArch64::LDNPSi:
3231 case AArch64::LDNPWi:
3232 case AArch64::LDNPXi:
3233 case AArch64::LDNT1B_ZRI:
3234 case AArch64::LDNT1D_ZRI:
3235 case AArch64::LDNT1H_ZRI:
3236 case AArch64::LDNT1W_ZRI:
3237 case AArch64::LDPDi:
3238 case AArch64::LDPQi:
3239 case AArch64::LDPSi:
3240 case AArch64::LDPWi:
3241 case AArch64::LDPXi:
3242 case AArch64::LDRBBpost:
3243 case AArch64::LDRBBpre:
3244 case AArch64::LDRBpost:
3245 case AArch64::LDRBpre:
3246 case AArch64::LDRDpost:
3247 case AArch64::LDRDpre:
3248 case AArch64::LDRHHpost:
3249 case AArch64::LDRHHpre:
3250 case AArch64::LDRHpost:
3251 case AArch64::LDRHpre:
3252 case AArch64::LDRQpost:
3253 case AArch64::LDRQpre:
3254 case AArch64::LDRSpost:
3255 case AArch64::LDRSpre:
3256 case AArch64::LDRWpost:
3257 case AArch64::LDRWpre:
3258 case AArch64::LDRXpost:
3259 case AArch64::LDRXpre:
3260 case AArch64::ST1B_D_IMM:
3261 case AArch64::ST1B_H_IMM:
3262 case AArch64::ST1B_IMM:
3263 case AArch64::ST1B_S_IMM:
3264 case AArch64::ST1D_IMM:
3265 case AArch64::ST1H_D_IMM:
3266 case AArch64::ST1H_IMM:
3267 case AArch64::ST1H_S_IMM:
3268 case AArch64::ST1W_D_IMM:
3269 case AArch64::ST1W_IMM:
3270 case AArch64::ST2B_IMM:
3271 case AArch64::ST2D_IMM:
3272 case AArch64::ST2H_IMM:
3273 case AArch64::ST2W_IMM:
3274 case AArch64::ST3B_IMM:
3275 case AArch64::ST3D_IMM:
3276 case AArch64::ST3H_IMM:
3277 case AArch64::ST3W_IMM:
3278 case AArch64::ST4B_IMM:
3279 case AArch64::ST4D_IMM:
3280 case AArch64::ST4H_IMM:
3281 case AArch64::ST4W_IMM:
3282 case AArch64::STGPi:
3283 case AArch64::STGPreIndex:
3284 case AArch64::STZGPreIndex:
3285 case AArch64::ST2GPreIndex:
3286 case AArch64::STZ2GPreIndex:
3287 case AArch64::STGPostIndex:
3288 case AArch64::STZGPostIndex:
3289 case AArch64::ST2GPostIndex:
3290 case AArch64::STZ2GPostIndex:
3291 case AArch64::STNPDi:
3292 case AArch64::STNPQi:
3293 case AArch64::STNPSi:
3294 case AArch64::STNPWi:
3295 case AArch64::STNPXi:
3296 case AArch64::STNT1B_ZRI:
3297 case AArch64::STNT1D_ZRI:
3298 case AArch64::STNT1H_ZRI:
3299 case AArch64::STNT1W_ZRI:
3300 case AArch64::STPDi:
3301 case AArch64::STPQi:
3302 case AArch64::STPSi:
3303 case AArch64::STPWi:
3304 case AArch64::STPXi:
3305 case AArch64::STRBBpost:
3306 case AArch64::STRBBpre:
3307 case AArch64::STRBpost:
3308 case AArch64::STRBpre:
3309 case AArch64::STRDpost:
3310 case AArch64::STRDpre:
3311 case AArch64::STRHHpost:
3312 case AArch64::STRHHpre:
3313 case AArch64::STRHpost:
3314 case AArch64::STRHpre:
3315 case AArch64::STRQpost:
3316 case AArch64::STRQpre:
3317 case AArch64::STRSpost:
3318 case AArch64::STRSpre:
3319 case AArch64::STRWpost:
3320 case AArch64::STRWpre:
3321 case AArch64::STRXpost:
3322 case AArch64::STRXpre:
3323 case AArch64::LD1B_2Z_IMM:
3324 case AArch64::LD1B_2Z_STRIDED_IMM:
3325 case AArch64::LD1H_2Z_IMM:
3326 case AArch64::LD1H_2Z_STRIDED_IMM:
3327 case AArch64::LD1W_2Z_IMM:
3328 case AArch64::LD1W_2Z_STRIDED_IMM:
3329 case AArch64::LD1D_2Z_IMM:
3330 case AArch64::LD1D_2Z_STRIDED_IMM:
3331 case AArch64::LD1B_4Z_IMM:
3332 case AArch64::LD1B_4Z_STRIDED_IMM:
3333 case AArch64::LD1H_4Z_IMM:
3334 case AArch64::LD1H_4Z_STRIDED_IMM:
3335 case AArch64::LD1W_4Z_IMM:
3336 case AArch64::LD1W_4Z_STRIDED_IMM:
3337 case AArch64::LD1D_4Z_IMM:
3338 case AArch64::LD1D_4Z_STRIDED_IMM:
3339 case AArch64::LD1B_2Z_IMM_PSEUDO:
3340 case AArch64::LD1H_2Z_IMM_PSEUDO:
3341 case AArch64::LD1W_2Z_IMM_PSEUDO:
3342 case AArch64::LD1D_2Z_IMM_PSEUDO:
3343 case AArch64::LD1B_4Z_IMM_PSEUDO:
3344 case AArch64::LD1H_4Z_IMM_PSEUDO:
3345 case AArch64::LD1W_4Z_IMM_PSEUDO:
3346 case AArch64::LD1D_4Z_IMM_PSEUDO:
3347 case AArch64::ST1B_2Z_IMM:
3348 case AArch64::ST1B_2Z_STRIDED_IMM:
3349 case AArch64::ST1H_2Z_IMM:
3350 case AArch64::ST1H_2Z_STRIDED_IMM:
3351 case AArch64::ST1W_2Z_IMM:
3352 case AArch64::ST1W_2Z_STRIDED_IMM:
3353 case AArch64::ST1D_2Z_IMM:
3354 case AArch64::ST1D_2Z_STRIDED_IMM:
3355 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
3356 case AArch64::LDNT1B_2Z_IMM:
3357 case AArch64::LDNT1B_2Z_STRIDED_IMM:
3358 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
3359 case AArch64::LDNT1H_2Z_IMM:
3360 case AArch64::LDNT1H_2Z_STRIDED_IMM:
3361 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
3362 case AArch64::LDNT1W_2Z_IMM:
3363 case AArch64::LDNT1W_2Z_STRIDED_IMM:
3364 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
3365 case AArch64::LDNT1D_2Z_IMM:
3366 case AArch64::LDNT1D_2Z_STRIDED_IMM:
3367 case AArch64::STNT1B_2Z_IMM:
3368 case AArch64::STNT1B_2Z_STRIDED_IMM:
3369 case AArch64::STNT1H_2Z_IMM:
3370 case AArch64::STNT1H_2Z_STRIDED_IMM:
3371 case AArch64::STNT1W_2Z_IMM:
3372 case AArch64::STNT1W_2Z_STRIDED_IMM:
3373 case AArch64::STNT1D_2Z_IMM:
3374 case AArch64::STNT1D_2Z_STRIDED_IMM:
3375 case AArch64::ST1B_2Z_IMM_PSEUDO:
3376 case AArch64::ST1H_2Z_IMM_PSEUDO:
3377 case AArch64::ST1W_2Z_IMM_PSEUDO:
3378 case AArch64::ST1D_2Z_IMM_PSEUDO:
3379 case AArch64::STNT1B_2Z_IMM_PSEUDO:
3380 case AArch64::STNT1H_2Z_IMM_PSEUDO:
3381 case AArch64::STNT1W_2Z_IMM_PSEUDO:
3382 case AArch64::STNT1D_2Z_IMM_PSEUDO:
3383 case AArch64::ST1B_4Z_IMM:
3384 case AArch64::ST1B_4Z_STRIDED_IMM:
3385 case AArch64::ST1H_4Z_IMM:
3386 case AArch64::ST1H_4Z_STRIDED_IMM:
3387 case AArch64::ST1W_4Z_IMM:
3388 case AArch64::ST1W_4Z_STRIDED_IMM:
3389 case AArch64::ST1D_4Z_IMM:
3390 case AArch64::ST1D_4Z_STRIDED_IMM:
3391 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
3392 case AArch64::LDNT1B_4Z_IMM:
3393 case AArch64::LDNT1B_4Z_STRIDED_IMM:
3394 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
3395 case AArch64::LDNT1H_4Z_IMM:
3396 case AArch64::LDNT1H_4Z_STRIDED_IMM:
3397 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
3398 case AArch64::LDNT1W_4Z_IMM:
3399 case AArch64::LDNT1W_4Z_STRIDED_IMM:
3400 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
3401 case AArch64::LDNT1D_4Z_IMM:
3402 case AArch64::LDNT1D_4Z_STRIDED_IMM:
3403 case AArch64::STNT1B_4Z_IMM:
3404 case AArch64::STNT1B_4Z_STRIDED_IMM:
3405 case AArch64::STNT1H_4Z_IMM:
3406 case AArch64::STNT1H_4Z_STRIDED_IMM:
3407 case AArch64::STNT1W_4Z_IMM:
3408 case AArch64::STNT1W_4Z_STRIDED_IMM:
3409 case AArch64::STNT1D_4Z_IMM:
3410 case AArch64::STNT1D_4Z_STRIDED_IMM:
3411 case AArch64::ST1B_4Z_IMM_PSEUDO:
3412 case AArch64::ST1H_4Z_IMM_PSEUDO:
3413 case AArch64::ST1W_4Z_IMM_PSEUDO:
3414 case AArch64::ST1D_4Z_IMM_PSEUDO:
3415 case AArch64::STNT1B_4Z_IMM_PSEUDO:
3416 case AArch64::STNT1H_4Z_IMM_PSEUDO:
3417 case AArch64::STNT1W_4Z_IMM_PSEUDO:
3418 case AArch64::STNT1D_4Z_IMM_PSEUDO:
3419 return 3;
3420 case AArch64::LDPDpost:
3421 case AArch64::LDPDpre:
3422 case AArch64::LDPQpost:
3423 case AArch64::LDPQpre:
3424 case AArch64::LDPSpost:
3425 case AArch64::LDPSpre:
3426 case AArch64::LDPWpost:
3427 case AArch64::LDPWpre:
3428 case AArch64::LDPXpost:
3429 case AArch64::LDPXpre:
3430 case AArch64::STGPpre:
3431 case AArch64::STGPpost:
3432 case AArch64::STPDpost:
3433 case AArch64::STPDpre:
3434 case AArch64::STPQpost:
3435 case AArch64::STPQpre:
3436 case AArch64::STPSpost:
3437 case AArch64::STPSpre:
3438 case AArch64::STPWpost:
3439 case AArch64::STPWpre:
3440 case AArch64::STPXpost:
3441 case AArch64::STPXpre:
3442 return 4;
3443 }
3444}
3445
3447 switch (MI.getOpcode()) {
3448 default:
3449 return false;
3450 // Scaled instructions.
3451 case AArch64::STRSui:
3452 case AArch64::STRDui:
3453 case AArch64::STRQui:
3454 case AArch64::STRXui:
3455 case AArch64::STRWui:
3456 case AArch64::LDRSui:
3457 case AArch64::LDRDui:
3458 case AArch64::LDRQui:
3459 case AArch64::LDRXui:
3460 case AArch64::LDRWui:
3461 case AArch64::LDRSWui:
3462 // Unscaled instructions.
3463 case AArch64::STURSi:
3464 case AArch64::STRSpre:
3465 case AArch64::STURDi:
3466 case AArch64::STRDpre:
3467 case AArch64::STURQi:
3468 case AArch64::STRQpre:
3469 case AArch64::STURWi:
3470 case AArch64::STRWpre:
3471 case AArch64::STURXi:
3472 case AArch64::STRXpre:
3473 case AArch64::LDURSi:
3474 case AArch64::LDRSpre:
3475 case AArch64::LDURDi:
3476 case AArch64::LDRDpre:
3477 case AArch64::LDURQi:
3478 case AArch64::LDRQpre:
3479 case AArch64::LDURWi:
3480 case AArch64::LDRWpre:
3481 case AArch64::LDURXi:
3482 case AArch64::LDRXpre:
3483 case AArch64::LDURSWi:
3484 case AArch64::LDRSWpre:
3485 // SVE instructions.
3486 case AArch64::LDR_ZXI:
3487 case AArch64::STR_ZXI:
3488 return true;
3489 }
3490}
3491
3493 switch (MI.getOpcode()) {
3494 default:
3495 assert((!MI.isCall() || !MI.isReturn()) &&
3496 "Unexpected instruction - was a new tail call opcode introduced?");
3497 return false;
3498 case AArch64::TCRETURNdi:
3499 case AArch64::TCRETURNri:
3500 case AArch64::TCRETURNrix16x17:
3501 case AArch64::TCRETURNrix17:
3502 case AArch64::TCRETURNrinotx16:
3503 case AArch64::TCRETURNriALL:
3504 case AArch64::AUTH_TCRETURN:
3505 case AArch64::AUTH_TCRETURN_BTI:
3506 return true;
3507 }
3508}
3509
3511 switch (Opc) {
3512 default:
3513 llvm_unreachable("Opcode has no flag setting equivalent!");
3514 // 32-bit cases:
3515 case AArch64::ADDWri:
3516 return AArch64::ADDSWri;
3517 case AArch64::ADDWrr:
3518 return AArch64::ADDSWrr;
3519 case AArch64::ADDWrs:
3520 return AArch64::ADDSWrs;
3521 case AArch64::ADDWrx:
3522 return AArch64::ADDSWrx;
3523 case AArch64::ANDWri:
3524 return AArch64::ANDSWri;
3525 case AArch64::ANDWrr:
3526 return AArch64::ANDSWrr;
3527 case AArch64::ANDWrs:
3528 return AArch64::ANDSWrs;
3529 case AArch64::BICWrr:
3530 return AArch64::BICSWrr;
3531 case AArch64::BICWrs:
3532 return AArch64::BICSWrs;
3533 case AArch64::SUBWri:
3534 return AArch64::SUBSWri;
3535 case AArch64::SUBWrr:
3536 return AArch64::SUBSWrr;
3537 case AArch64::SUBWrs:
3538 return AArch64::SUBSWrs;
3539 case AArch64::SUBWrx:
3540 return AArch64::SUBSWrx;
3541 // 64-bit cases:
3542 case AArch64::ADDXri:
3543 return AArch64::ADDSXri;
3544 case AArch64::ADDXrr:
3545 return AArch64::ADDSXrr;
3546 case AArch64::ADDXrs:
3547 return AArch64::ADDSXrs;
3548 case AArch64::ADDXrx:
3549 return AArch64::ADDSXrx;
3550 case AArch64::ANDXri:
3551 return AArch64::ANDSXri;
3552 case AArch64::ANDXrr:
3553 return AArch64::ANDSXrr;
3554 case AArch64::ANDXrs:
3555 return AArch64::ANDSXrs;
3556 case AArch64::BICXrr:
3557 return AArch64::BICSXrr;
3558 case AArch64::BICXrs:
3559 return AArch64::BICSXrs;
3560 case AArch64::SUBXri:
3561 return AArch64::SUBSXri;
3562 case AArch64::SUBXrr:
3563 return AArch64::SUBSXrr;
3564 case AArch64::SUBXrs:
3565 return AArch64::SUBSXrs;
3566 case AArch64::SUBXrx:
3567 return AArch64::SUBSXrx;
3568 // SVE instructions:
3569 case AArch64::AND_PPzPP:
3570 return AArch64::ANDS_PPzPP;
3571 case AArch64::BIC_PPzPP:
3572 return AArch64::BICS_PPzPP;
3573 case AArch64::EOR_PPzPP:
3574 return AArch64::EORS_PPzPP;
3575 case AArch64::NAND_PPzPP:
3576 return AArch64::NANDS_PPzPP;
3577 case AArch64::NOR_PPzPP:
3578 return AArch64::NORS_PPzPP;
3579 case AArch64::ORN_PPzPP:
3580 return AArch64::ORNS_PPzPP;
3581 case AArch64::ORR_PPzPP:
3582 return AArch64::ORRS_PPzPP;
3583 case AArch64::BRKA_PPzP:
3584 return AArch64::BRKAS_PPzP;
3585 case AArch64::BRKPA_PPzPP:
3586 return AArch64::BRKPAS_PPzPP;
3587 case AArch64::BRKB_PPzP:
3588 return AArch64::BRKBS_PPzP;
3589 case AArch64::BRKPB_PPzPP:
3590 return AArch64::BRKPBS_PPzPP;
3591 case AArch64::BRKN_PPzP:
3592 return AArch64::BRKNS_PPzP;
3593 case AArch64::RDFFR_PPz:
3594 return AArch64::RDFFRS_PPz;
3595 case AArch64::PTRUE_B:
3596 return AArch64::PTRUES_B;
3597 }
3598}
3599
3600// Is this a candidate for ld/st merging or pairing? For example, we don't
3601// touch volatiles or load/stores that have a hint to avoid pair formation.
3603
3604 bool IsPreLdSt = isPreLdSt(MI);
3605
3606 // If this is a volatile load/store, don't mess with it.
3607 if (MI.hasOrderedMemoryRef())
3608 return false;
3609
3610 // Make sure this is a reg/fi+imm (as opposed to an address reloc).
3611 // For Pre-inc LD/ST, the operand is shifted by one.
3612 assert((MI.getOperand(IsPreLdSt ? 2 : 1).isReg() ||
3613 MI.getOperand(IsPreLdSt ? 2 : 1).isFI()) &&
3614 "Expected a reg or frame index operand.");
3615
3616 // For Pre-indexed addressing quadword instructions, the third operand is the
3617 // immediate value.
3618 bool IsImmPreLdSt = IsPreLdSt && MI.getOperand(3).isImm();
3619
3620 if (!MI.getOperand(2).isImm() && !IsImmPreLdSt)
3621 return false;
3622
3623 // Can't merge/pair if the instruction modifies the base register.
3624 // e.g., ldr x0, [x0]
3625 // This case will never occur with an FI base.
3626 // However, if the instruction is an LDR<S,D,Q,W,X,SW>pre or
3627 // STR<S,D,Q,W,X>pre, it can be merged.
3628 // For example:
3629 // ldr q0, [x11, #32]!
3630 // ldr q1, [x11, #16]
3631 // to
3632 // ldp q0, q1, [x11, #32]!
3633 if (MI.getOperand(1).isReg() && !IsPreLdSt) {
3634 Register BaseReg = MI.getOperand(1).getReg();
3636 if (MI.modifiesRegister(BaseReg, TRI))
3637 return false;
3638 }
3639
3640 // Pairing SVE fills/spills is only valid for little-endian targets that
3641 // implement VLS 128.
3642 switch (MI.getOpcode()) {
3643 default:
3644 break;
3645 case AArch64::LDR_ZXI:
3646 case AArch64::STR_ZXI:
3647 if (!Subtarget.isLittleEndian() ||
3648 Subtarget.getSVEVectorSizeInBits() != 128)
3649 return false;
3650 }
3651
3652 // Check if this load/store has a hint to avoid pair formation.
3653 // MachineMemOperands hints are set by the AArch64StorePairSuppress pass.
3655 return false;
3656
3657 // Do not pair any callee-save store/reload instructions in the
3658 // prologue/epilogue if the CFI information encoded the operations as separate
3659 // instructions, as that will cause the size of the actual prologue to mismatch
3660 // with the prologue size recorded in the Windows CFI.
3661 const MCAsmInfo &MAI = MI.getMF()->getTarget().getMCAsmInfo();
3662 bool NeedsWinCFI =
3663 MAI.usesWindowsCFI() && MI.getMF()->getFunction().needsUnwindTableEntry();
3664 if (NeedsWinCFI && (MI.getFlag(MachineInstr::FrameSetup) ||
3666 return false;
3667
3668 // On some CPUs quad load/store pairs are slower than two single load/stores.
3669 if (Subtarget.isPaired128Slow()) {
3670 switch (MI.getOpcode()) {
3671 default:
3672 break;
3673 case AArch64::LDURQi:
3674 case AArch64::STURQi:
3675 case AArch64::LDRQui:
3676 case AArch64::STRQui:
3677 return false;
3678 }
3679 }
3680
3681 return true;
3682}
3683
3686 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width,
3687 const TargetRegisterInfo *TRI) const {
3688 if (!LdSt.mayLoadOrStore())
3689 return false;
3690
3691 const MachineOperand *BaseOp;
3692 TypeSize WidthN(0, false);
3693 if (!getMemOperandWithOffsetWidth(LdSt, BaseOp, Offset, OffsetIsScalable,
3694 WidthN, TRI))
3695 return false;
3696 // The maximum vscale is 16 under AArch64, return the maximal extent for the
3697 // vector.
3698 Width = LocationSize::precise(WidthN);
3699 BaseOps.push_back(BaseOp);
3700 return true;
3701}
3702
3703std::optional<ExtAddrMode>
3705 const TargetRegisterInfo *TRI) const {
3706 const MachineOperand *Base; // Filled with the base operand of MI.
3707 int64_t Offset; // Filled with the offset of MI.
3708 bool OffsetIsScalable;
3709 if (!getMemOperandWithOffset(MemI, Base, Offset, OffsetIsScalable, TRI))
3710 return std::nullopt;
3711
3712 if (!Base->isReg())
3713 return std::nullopt;
3714 ExtAddrMode AM;
3715 AM.BaseReg = Base->getReg();
3716 AM.Displacement = Offset;
3717 AM.ScaledReg = 0;
3718 AM.Scale = 0;
3719 return AM;
3720}
3721
3723 Register Reg,
3724 const MachineInstr &AddrI,
3725 ExtAddrMode &AM) const {
3726 // Filter out instructions into which we cannot fold.
3727 unsigned NumBytes;
3728 int64_t OffsetScale = 1;
3729 switch (MemI.getOpcode()) {
3730 default:
3731 return false;
3732
3733 case AArch64::LDURQi:
3734 case AArch64::STURQi:
3735 NumBytes = 16;
3736 break;
3737
3738 case AArch64::LDURDi:
3739 case AArch64::STURDi:
3740 case AArch64::LDURXi:
3741 case AArch64::STURXi:
3742 NumBytes = 8;
3743 break;
3744
3745 case AArch64::LDURWi:
3746 case AArch64::LDURSWi:
3747 case AArch64::STURWi:
3748 NumBytes = 4;
3749 break;
3750
3751 case AArch64::LDURHi:
3752 case AArch64::STURHi:
3753 case AArch64::LDURHHi:
3754 case AArch64::STURHHi:
3755 case AArch64::LDURSHXi:
3756 case AArch64::LDURSHWi:
3757 NumBytes = 2;
3758 break;
3759
3760 case AArch64::LDRBroX:
3761 case AArch64::LDRBBroX:
3762 case AArch64::LDRSBXroX:
3763 case AArch64::LDRSBWroX:
3764 case AArch64::STRBroX:
3765 case AArch64::STRBBroX:
3766 case AArch64::LDURBi:
3767 case AArch64::LDURBBi:
3768 case AArch64::LDURSBXi:
3769 case AArch64::LDURSBWi:
3770 case AArch64::STURBi:
3771 case AArch64::STURBBi:
3772 case AArch64::LDRBui:
3773 case AArch64::LDRBBui:
3774 case AArch64::LDRSBXui:
3775 case AArch64::LDRSBWui:
3776 case AArch64::STRBui:
3777 case AArch64::STRBBui:
3778 NumBytes = 1;
3779 break;
3780
3781 case AArch64::LDRQroX:
3782 case AArch64::STRQroX:
3783 case AArch64::LDRQui:
3784 case AArch64::STRQui:
3785 NumBytes = 16;
3786 OffsetScale = 16;
3787 break;
3788
3789 case AArch64::LDRDroX:
3790 case AArch64::STRDroX:
3791 case AArch64::LDRXroX:
3792 case AArch64::STRXroX:
3793 case AArch64::LDRDui:
3794 case AArch64::STRDui:
3795 case AArch64::LDRXui:
3796 case AArch64::STRXui:
3797 NumBytes = 8;
3798 OffsetScale = 8;
3799 break;
3800
3801 case AArch64::LDRWroX:
3802 case AArch64::LDRSWroX:
3803 case AArch64::STRWroX:
3804 case AArch64::LDRWui:
3805 case AArch64::LDRSWui:
3806 case AArch64::STRWui:
3807 NumBytes = 4;
3808 OffsetScale = 4;
3809 break;
3810
3811 case AArch64::LDRHroX:
3812 case AArch64::STRHroX:
3813 case AArch64::LDRHHroX:
3814 case AArch64::STRHHroX:
3815 case AArch64::LDRSHXroX:
3816 case AArch64::LDRSHWroX:
3817 case AArch64::LDRHui:
3818 case AArch64::STRHui:
3819 case AArch64::LDRHHui:
3820 case AArch64::STRHHui:
3821 case AArch64::LDRSHXui:
3822 case AArch64::LDRSHWui:
3823 NumBytes = 2;
3824 OffsetScale = 2;
3825 break;
3826 }
3827
3828 // Check the fold operand is not the loaded/stored value.
3829 const MachineOperand &BaseRegOp = MemI.getOperand(0);
3830 if (BaseRegOp.isReg() && BaseRegOp.getReg() == Reg)
3831 return false;
3832
3833 // Handle memory instructions with a [Reg, Reg] addressing mode.
3834 if (MemI.getOperand(2).isReg()) {
3835 // Bail if the addressing mode already includes extension of the offset
3836 // register.
3837 if (MemI.getOperand(3).getImm())
3838 return false;
3839
3840 // Check if we actually have a scaled offset.
3841 if (MemI.getOperand(4).getImm() == 0)
3842 OffsetScale = 1;
3843
3844 // If the address instructions is folded into the base register, then the
3845 // addressing mode must not have a scale. Then we can swap the base and the
3846 // scaled registers.
3847 if (MemI.getOperand(1).getReg() == Reg && OffsetScale != 1)
3848 return false;
3849
3850 switch (AddrI.getOpcode()) {
3851 default:
3852 return false;
3853
3854 case AArch64::SBFMXri:
3855 // sxtw Xa, Wm
3856 // ldr Xd, [Xn, Xa, lsl #N]
3857 // ->
3858 // ldr Xd, [Xn, Wm, sxtw #N]
3859 if (AddrI.getOperand(2).getImm() != 0 ||
3860 AddrI.getOperand(3).getImm() != 31)
3861 return false;
3862
3863 AM.BaseReg = MemI.getOperand(1).getReg();
3864 if (AM.BaseReg == Reg)
3865 AM.BaseReg = MemI.getOperand(2).getReg();
3866 AM.ScaledReg = AddrI.getOperand(1).getReg();
3867 AM.Scale = OffsetScale;
3868 AM.Displacement = 0;
3870 return true;
3871
3872 case TargetOpcode::SUBREG_TO_REG: {
3873 // mov Wa, Wm
3874 // ldr Xd, [Xn, Xa, lsl #N]
3875 // ->
3876 // ldr Xd, [Xn, Wm, uxtw #N]
3877
3878 // Zero-extension looks like an ORRWrs followed by a SUBREG_TO_REG.
3879 if (AddrI.getOperand(2).getImm() != AArch64::sub_32)
3880 return false;
3881
3882 const MachineRegisterInfo &MRI = AddrI.getMF()->getRegInfo();
3883 Register OffsetReg = AddrI.getOperand(1).getReg();
3884 if (!OffsetReg.isVirtual() || !MRI.hasOneNonDBGUse(OffsetReg))
3885 return false;
3886
3887 const MachineInstr &DefMI = *MRI.getVRegDef(OffsetReg);
3888 if (DefMI.getOpcode() != AArch64::ORRWrs ||
3889 DefMI.getOperand(1).getReg() != AArch64::WZR ||
3890 DefMI.getOperand(3).getImm() != 0)
3891 return false;
3892
3893 AM.BaseReg = MemI.getOperand(1).getReg();
3894 if (AM.BaseReg == Reg)
3895 AM.BaseReg = MemI.getOperand(2).getReg();
3896 AM.ScaledReg = DefMI.getOperand(2).getReg();
3897 AM.Scale = OffsetScale;
3898 AM.Displacement = 0;
3900 return true;
3901 }
3902 }
3903 }
3904
3905 // Handle memory instructions with a [Reg, #Imm] addressing mode.
3906
3907 // Check we are not breaking a potential conversion to an LDP.
3908 auto validateOffsetForLDP = [](unsigned NumBytes, int64_t OldOffset,
3909 int64_t NewOffset) -> bool {
3910 int64_t MinOffset, MaxOffset;
3911 switch (NumBytes) {
3912 default:
3913 return true;
3914 case 4:
3915 MinOffset = -256;
3916 MaxOffset = 252;
3917 break;
3918 case 8:
3919 MinOffset = -512;
3920 MaxOffset = 504;
3921 break;
3922 case 16:
3923 MinOffset = -1024;
3924 MaxOffset = 1008;
3925 break;
3926 }
3927 return OldOffset < MinOffset || OldOffset > MaxOffset ||
3928 (NewOffset >= MinOffset && NewOffset <= MaxOffset);
3929 };
3930 auto canFoldAddSubImmIntoAddrMode = [&](int64_t Disp) -> bool {
3931 int64_t OldOffset = MemI.getOperand(2).getImm() * OffsetScale;
3932 int64_t NewOffset = OldOffset + Disp;
3933 if (!isLegalAddressingMode(NumBytes, NewOffset, /* Scale */ 0))
3934 return false;
3935 // If the old offset would fit into an LDP, but the new offset wouldn't,
3936 // bail out.
3937 if (!validateOffsetForLDP(NumBytes, OldOffset, NewOffset))
3938 return false;
3939 AM.BaseReg = AddrI.getOperand(1).getReg();
3940 AM.ScaledReg = 0;
3941 AM.Scale = 0;
3942 AM.Displacement = NewOffset;
3944 return true;
3945 };
3946
3947 auto canFoldAddRegIntoAddrMode =
3948 [&](int64_t Scale,
3950 if (MemI.getOperand(2).getImm() != 0)
3951 return false;
3952 if ((unsigned)Scale != Scale)
3953 return false;
3954 if (!isLegalAddressingMode(NumBytes, /* Offset */ 0, Scale))
3955 return false;
3956 AM.BaseReg = AddrI.getOperand(1).getReg();
3957 AM.ScaledReg = AddrI.getOperand(2).getReg();
3958 AM.Scale = Scale;
3959 AM.Displacement = 0;
3960 AM.Form = Form;
3961 return true;
3962 };
3963
3964 auto avoidSlowSTRQ = [&](const MachineInstr &MemI) {
3965 unsigned Opcode = MemI.getOpcode();
3966 return (Opcode == AArch64::STURQi || Opcode == AArch64::STRQui) &&
3967 Subtarget.isSTRQroSlow();
3968 };
3969
3970 int64_t Disp = 0;
3971 const bool OptSize = MemI.getMF()->getFunction().hasOptSize();
3972 switch (AddrI.getOpcode()) {
3973 default:
3974 return false;
3975
3976 case AArch64::ADDXri:
3977 // add Xa, Xn, #N
3978 // ldr Xd, [Xa, #M]
3979 // ->
3980 // ldr Xd, [Xn, #N'+M]
3981 Disp = AddrI.getOperand(2).getImm() << AddrI.getOperand(3).getImm();
3982 return canFoldAddSubImmIntoAddrMode(Disp);
3983
3984 case AArch64::SUBXri:
3985 // sub Xa, Xn, #N
3986 // ldr Xd, [Xa, #M]
3987 // ->
3988 // ldr Xd, [Xn, #N'+M]
3989 Disp = AddrI.getOperand(2).getImm() << AddrI.getOperand(3).getImm();
3990 return canFoldAddSubImmIntoAddrMode(-Disp);
3991
3992 case AArch64::ADDXrs: {
3993 // add Xa, Xn, Xm, lsl #N
3994 // ldr Xd, [Xa]
3995 // ->
3996 // ldr Xd, [Xn, Xm, lsl #N]
3997
3998 // Don't fold the add if the result would be slower, unless optimising for
3999 // size.
4000 unsigned Shift = static_cast<unsigned>(AddrI.getOperand(3).getImm());
4002 return false;
4003 Shift = AArch64_AM::getShiftValue(Shift);
4004 if (!OptSize) {
4005 if (Shift != 2 && Shift != 3 && Subtarget.hasAddrLSLSlow14())
4006 return false;
4007 if (avoidSlowSTRQ(MemI))
4008 return false;
4009 }
4010 return canFoldAddRegIntoAddrMode(1ULL << Shift);
4011 }
4012
4013 case AArch64::ADDXrr:
4014 // add Xa, Xn, Xm
4015 // ldr Xd, [Xa]
4016 // ->
4017 // ldr Xd, [Xn, Xm, lsl #0]
4018
4019 // Don't fold the add if the result would be slower, unless optimising for
4020 // size.
4021 if (!OptSize && avoidSlowSTRQ(MemI))
4022 return false;
4023 return canFoldAddRegIntoAddrMode(1);
4024
4025 case AArch64::ADDXrx:
4026 // add Xa, Xn, Wm, {s,u}xtw #N
4027 // ldr Xd, [Xa]
4028 // ->
4029 // ldr Xd, [Xn, Wm, {s,u}xtw #N]
4030
4031 // Don't fold the add if the result would be slower, unless optimising for
4032 // size.
4033 if (!OptSize && avoidSlowSTRQ(MemI))
4034 return false;
4035
4036 // Can fold only sign-/zero-extend of a word.
4037 unsigned Imm = static_cast<unsigned>(AddrI.getOperand(3).getImm());
4039 if (Extend != AArch64_AM::UXTW && Extend != AArch64_AM::SXTW)
4040 return false;
4041
4042 return canFoldAddRegIntoAddrMode(
4046 }
4047}
4048
4049// Given an opcode for an instruction with a [Reg, #Imm] addressing mode,
4050// return the opcode of an instruction performing the same operation, but using
4051// the [Reg, Reg] addressing mode.
4052static unsigned regOffsetOpcode(unsigned Opcode) {
4053 switch (Opcode) {
4054 default:
4055 llvm_unreachable("Address folding not implemented for instruction");
4056
4057 case AArch64::LDURQi:
4058 case AArch64::LDRQui:
4059 return AArch64::LDRQroX;
4060 case AArch64::STURQi:
4061 case AArch64::STRQui:
4062 return AArch64::STRQroX;
4063 case AArch64::LDURDi:
4064 case AArch64::LDRDui:
4065 return AArch64::LDRDroX;
4066 case AArch64::STURDi:
4067 case AArch64::STRDui:
4068 return AArch64::STRDroX;
4069 case AArch64::LDURXi:
4070 case AArch64::LDRXui:
4071 return AArch64::LDRXroX;
4072 case AArch64::STURXi:
4073 case AArch64::STRXui:
4074 return AArch64::STRXroX;
4075 case AArch64::LDURWi:
4076 case AArch64::LDRWui:
4077 return AArch64::LDRWroX;
4078 case AArch64::LDURSWi:
4079 case AArch64::LDRSWui:
4080 return AArch64::LDRSWroX;
4081 case AArch64::STURWi:
4082 case AArch64::STRWui:
4083 return AArch64::STRWroX;
4084 case AArch64::LDURHi:
4085 case AArch64::LDRHui:
4086 return AArch64::LDRHroX;
4087 case AArch64::STURHi:
4088 case AArch64::STRHui:
4089 return AArch64::STRHroX;
4090 case AArch64::LDURHHi:
4091 case AArch64::LDRHHui:
4092 return AArch64::LDRHHroX;
4093 case AArch64::STURHHi:
4094 case AArch64::STRHHui:
4095 return AArch64::STRHHroX;
4096 case AArch64::LDURSHXi:
4097 case AArch64::LDRSHXui:
4098 return AArch64::LDRSHXroX;
4099 case AArch64::LDURSHWi:
4100 case AArch64::LDRSHWui:
4101 return AArch64::LDRSHWroX;
4102 case AArch64::LDURBi:
4103 case AArch64::LDRBui:
4104 return AArch64::LDRBroX;
4105 case AArch64::LDURBBi:
4106 case AArch64::LDRBBui:
4107 return AArch64::LDRBBroX;
4108 case AArch64::LDURSBXi:
4109 case AArch64::LDRSBXui:
4110 return AArch64::LDRSBXroX;
4111 case AArch64::LDURSBWi:
4112 case AArch64::LDRSBWui:
4113 return AArch64::LDRSBWroX;
4114 case AArch64::STURBi:
4115 case AArch64::STRBui:
4116 return AArch64::STRBroX;
4117 case AArch64::STURBBi:
4118 case AArch64::STRBBui:
4119 return AArch64::STRBBroX;
4120 }
4121}
4122
4123// Given an opcode for an instruction with a [Reg, #Imm] addressing mode, return
4124// the opcode of an instruction performing the same operation, but using the
4125// [Reg, #Imm] addressing mode with scaled offset.
4126unsigned scaledOffsetOpcode(unsigned Opcode, unsigned &Scale) {
4127 switch (Opcode) {
4128 default:
4129 llvm_unreachable("Address folding not implemented for instruction");
4130
4131 case AArch64::LDURQi:
4132 Scale = 16;
4133 return AArch64::LDRQui;
4134 case AArch64::STURQi:
4135 Scale = 16;
4136 return AArch64::STRQui;
4137 case AArch64::LDURDi:
4138 Scale = 8;
4139 return AArch64::LDRDui;
4140 case AArch64::STURDi:
4141 Scale = 8;
4142 return AArch64::STRDui;
4143 case AArch64::LDURXi:
4144 Scale = 8;
4145 return AArch64::LDRXui;
4146 case AArch64::STURXi:
4147 Scale = 8;
4148 return AArch64::STRXui;
4149 case AArch64::LDURWi:
4150 Scale = 4;
4151 return AArch64::LDRWui;
4152 case AArch64::LDURSWi:
4153 Scale = 4;
4154 return AArch64::LDRSWui;
4155 case AArch64::STURWi:
4156 Scale = 4;
4157 return AArch64::STRWui;
4158 case AArch64::LDURHi:
4159 Scale = 2;
4160 return AArch64::LDRHui;
4161 case AArch64::STURHi:
4162 Scale = 2;
4163 return AArch64::STRHui;
4164 case AArch64::LDURHHi:
4165 Scale = 2;
4166 return AArch64::LDRHHui;
4167 case AArch64::STURHHi:
4168 Scale = 2;
4169 return AArch64::STRHHui;
4170 case AArch64::LDURSHXi:
4171 Scale = 2;
4172 return AArch64::LDRSHXui;
4173 case AArch64::LDURSHWi:
4174 Scale = 2;
4175 return AArch64::LDRSHWui;
4176 case AArch64::LDURBi:
4177 Scale = 1;
4178 return AArch64::LDRBui;
4179 case AArch64::LDURBBi:
4180 Scale = 1;
4181 return AArch64::LDRBBui;
4182 case AArch64::LDURSBXi:
4183 Scale = 1;
4184 return AArch64::LDRSBXui;
4185 case AArch64::LDURSBWi:
4186 Scale = 1;
4187 return AArch64::LDRSBWui;
4188 case AArch64::STURBi:
4189 Scale = 1;
4190 return AArch64::STRBui;
4191 case AArch64::STURBBi:
4192 Scale = 1;
4193 return AArch64::STRBBui;
4194 case AArch64::LDRQui:
4195 case AArch64::STRQui:
4196 Scale = 16;
4197 return Opcode;
4198 case AArch64::LDRDui:
4199 case AArch64::STRDui:
4200 case AArch64::LDRXui:
4201 case AArch64::STRXui:
4202 Scale = 8;
4203 return Opcode;
4204 case AArch64::LDRWui:
4205 case AArch64::LDRSWui:
4206 case AArch64::STRWui:
4207 Scale = 4;
4208 return Opcode;
4209 case AArch64::LDRHui:
4210 case AArch64::STRHui:
4211 case AArch64::LDRHHui:
4212 case AArch64::STRHHui:
4213 case AArch64::LDRSHXui:
4214 case AArch64::LDRSHWui:
4215 Scale = 2;
4216 return Opcode;
4217 case AArch64::LDRBui:
4218 case AArch64::LDRBBui:
4219 case AArch64::LDRSBXui:
4220 case AArch64::LDRSBWui:
4221 case AArch64::STRBui:
4222 case AArch64::STRBBui:
4223 Scale = 1;
4224 return Opcode;
4225 }
4226}
4227
4228// Given an opcode for an instruction with a [Reg, #Imm] addressing mode, return
4229// the opcode of an instruction performing the same operation, but using the
4230// [Reg, #Imm] addressing mode with unscaled offset.
4231unsigned unscaledOffsetOpcode(unsigned Opcode) {
4232 switch (Opcode) {
4233 default:
4234 llvm_unreachable("Address folding not implemented for instruction");
4235
4236 case AArch64::LDURQi:
4237 case AArch64::STURQi:
4238 case AArch64::LDURDi:
4239 case AArch64::STURDi:
4240 case AArch64::LDURXi:
4241 case AArch64::STURXi:
4242 case AArch64::LDURWi:
4243 case AArch64::LDURSWi:
4244 case AArch64::STURWi:
4245 case AArch64::LDURHi:
4246 case AArch64::STURHi:
4247 case AArch64::LDURHHi:
4248 case AArch64::STURHHi:
4249 case AArch64::LDURSHXi:
4250 case AArch64::LDURSHWi:
4251 case AArch64::LDURBi:
4252 case AArch64::STURBi:
4253 case AArch64::LDURBBi:
4254 case AArch64::STURBBi:
4255 case AArch64::LDURSBWi:
4256 case AArch64::LDURSBXi:
4257 return Opcode;
4258 case AArch64::LDRQui:
4259 return AArch64::LDURQi;
4260 case AArch64::STRQui:
4261 return AArch64::STURQi;
4262 case AArch64::LDRDui:
4263 return AArch64::LDURDi;
4264 case AArch64::STRDui:
4265 return AArch64::STURDi;
4266 case AArch64::LDRXui:
4267 return AArch64::LDURXi;
4268 case AArch64::STRXui:
4269 return AArch64::STURXi;
4270 case AArch64::LDRWui:
4271 return AArch64::LDURWi;
4272 case AArch64::LDRSWui:
4273 return AArch64::LDURSWi;
4274 case AArch64::STRWui:
4275 return AArch64::STURWi;
4276 case AArch64::LDRHui:
4277 return AArch64::LDURHi;
4278 case AArch64::STRHui:
4279 return AArch64::STURHi;
4280 case AArch64::LDRHHui:
4281 return AArch64::LDURHHi;
4282 case AArch64::STRHHui:
4283 return AArch64::STURHHi;
4284 case AArch64::LDRSHXui:
4285 return AArch64::LDURSHXi;
4286 case AArch64::LDRSHWui:
4287 return AArch64::LDURSHWi;
4288 case AArch64::LDRBBui:
4289 return AArch64::LDURBBi;
4290 case AArch64::LDRBui:
4291 return AArch64::LDURBi;
4292 case AArch64::STRBBui:
4293 return AArch64::STURBBi;
4294 case AArch64::STRBui:
4295 return AArch64::STURBi;
4296 case AArch64::LDRSBWui:
4297 return AArch64::LDURSBWi;
4298 case AArch64::LDRSBXui:
4299 return AArch64::LDURSBXi;
4300 }
4301}
4302
4303// Given the opcode of a memory load/store instruction, return the opcode of an
4304// instruction performing the same operation, but using
4305// the [Reg, Reg, {s,u}xtw #N] addressing mode with sign-/zero-extend of the
4306// offset register.
4307static unsigned offsetExtendOpcode(unsigned Opcode) {
4308 switch (Opcode) {
4309 default:
4310 llvm_unreachable("Address folding not implemented for instruction");
4311
4312 case AArch64::LDRQroX:
4313 case AArch64::LDURQi:
4314 case AArch64::LDRQui:
4315 return AArch64::LDRQroW;
4316 case AArch64::STRQroX:
4317 case AArch64::STURQi:
4318 case AArch64::STRQui:
4319 return AArch64::STRQroW;
4320 case AArch64::LDRDroX:
4321 case AArch64::LDURDi:
4322 case AArch64::LDRDui:
4323 return AArch64::LDRDroW;
4324 case AArch64::STRDroX:
4325 case AArch64::STURDi:
4326 case AArch64::STRDui:
4327 return AArch64::STRDroW;
4328 case AArch64::LDRXroX:
4329 case AArch64::LDURXi:
4330 case AArch64::LDRXui:
4331 return AArch64::LDRXroW;
4332 case AArch64::STRXroX:
4333 case AArch64::STURXi:
4334 case AArch64::STRXui:
4335 return AArch64::STRXroW;
4336 case AArch64::LDRWroX:
4337 case AArch64::LDURWi:
4338 case AArch64::LDRWui:
4339 return AArch64::LDRWroW;
4340 case AArch64::LDRSWroX:
4341 case AArch64::LDURSWi:
4342 case AArch64::LDRSWui:
4343 return AArch64::LDRSWroW;
4344 case AArch64::STRWroX:
4345 case AArch64::STURWi:
4346 case AArch64::STRWui:
4347 return AArch64::STRWroW;
4348 case AArch64::LDRHroX:
4349 case AArch64::LDURHi:
4350 case AArch64::LDRHui:
4351 return AArch64::LDRHroW;
4352 case AArch64::STRHroX:
4353 case AArch64::STURHi:
4354 case AArch64::STRHui:
4355 return AArch64::STRHroW;
4356 case AArch64::LDRHHroX:
4357 case AArch64::LDURHHi:
4358 case AArch64::LDRHHui:
4359 return AArch64::LDRHHroW;
4360 case AArch64::STRHHroX:
4361 case AArch64::STURHHi:
4362 case AArch64::STRHHui:
4363 return AArch64::STRHHroW;
4364 case AArch64::LDRSHXroX:
4365 case AArch64::LDURSHXi:
4366 case AArch64::LDRSHXui:
4367 return AArch64::LDRSHXroW;
4368 case AArch64::LDRSHWroX:
4369 case AArch64::LDURSHWi:
4370 case AArch64::LDRSHWui:
4371 return AArch64::LDRSHWroW;
4372 case AArch64::LDRBroX:
4373 case AArch64::LDURBi:
4374 case AArch64::LDRBui:
4375 return AArch64::LDRBroW;
4376 case AArch64::LDRBBroX:
4377 case AArch64::LDURBBi:
4378 case AArch64::LDRBBui:
4379 return AArch64::LDRBBroW;
4380 case AArch64::LDRSBXroX:
4381 case AArch64::LDURSBXi:
4382 case AArch64::LDRSBXui:
4383 return AArch64::LDRSBXroW;
4384 case AArch64::LDRSBWroX:
4385 case AArch64::LDURSBWi:
4386 case AArch64::LDRSBWui:
4387 return AArch64::LDRSBWroW;
4388 case AArch64::STRBroX:
4389 case AArch64::STURBi:
4390 case AArch64::STRBui:
4391 return AArch64::STRBroW;
4392 case AArch64::STRBBroX:
4393 case AArch64::STURBBi:
4394 case AArch64::STRBBui:
4395 return AArch64::STRBBroW;
4396 }
4397}
4398
4400 const ExtAddrMode &AM) const {
4401
4402 const DebugLoc &DL = MemI.getDebugLoc();
4403 MachineBasicBlock &MBB = *MemI.getParent();
4404 MachineRegisterInfo &MRI = MemI.getMF()->getRegInfo();
4405
4407 if (AM.ScaledReg) {
4408 // The new instruction will be in the form `ldr Rt, [Xn, Xm, lsl #imm]`.
4409 unsigned Opcode = regOffsetOpcode(MemI.getOpcode());
4410 MRI.constrainRegClass(AM.BaseReg, &AArch64::GPR64spRegClass);
4411 auto B = BuildMI(MBB, MemI, DL, get(Opcode))
4412 .addReg(MemI.getOperand(0).getReg(),
4413 getDefRegState(MemI.mayLoad()))
4414 .addReg(AM.BaseReg)
4415 .addReg(AM.ScaledReg)
4416 .addImm(0)
4417 .addImm(AM.Scale > 1)
4418 .setMemRefs(MemI.memoperands())
4419 .setMIFlags(MemI.getFlags());
4420 return B.getInstr();
4421 }
4422
4423 assert(AM.ScaledReg == 0 && AM.Scale == 0 &&
4424 "Addressing mode not supported for folding");
4425
4426 // The new instruction will be in the form `ld[u]r Rt, [Xn, #imm]`.
4427 unsigned Scale = 1;
4428 unsigned Opcode = MemI.getOpcode();
4429 if (isInt<9>(AM.Displacement))
4430 Opcode = unscaledOffsetOpcode(Opcode);
4431 else
4432 Opcode = scaledOffsetOpcode(Opcode, Scale);
4433
4434 auto B =
4435 BuildMI(MBB, MemI, DL, get(Opcode))
4436 .addReg(MemI.getOperand(0).getReg(), getDefRegState(MemI.mayLoad()))
4437 .addReg(AM.BaseReg)
4438 .addImm(AM.Displacement / Scale)
4439 .setMemRefs(MemI.memoperands())
4440 .setMIFlags(MemI.getFlags());
4441 return B.getInstr();
4442 }
4443
4446 // The new instruction will be in the form `ldr Rt, [Xn, Wm, {s,u}xtw #N]`.
4447 assert(AM.ScaledReg && !AM.Displacement &&
4448 "Address offset can be a register or an immediate, but not both");
4449 unsigned Opcode = offsetExtendOpcode(MemI.getOpcode());
4450 MRI.constrainRegClass(AM.BaseReg, &AArch64::GPR64spRegClass);
4451 // Make sure the offset register is in the correct register class.
4452 Register OffsetReg = AM.ScaledReg;
4453 const TargetRegisterClass *RC = MRI.getRegClass(OffsetReg);
4454 if (RC->hasSuperClassEq(&AArch64::GPR64RegClass)) {
4455 OffsetReg = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
4456 BuildMI(MBB, MemI, DL, get(TargetOpcode::COPY), OffsetReg)
4457 .addReg(AM.ScaledReg, {}, AArch64::sub_32);
4458 }
4459 auto B =
4460 BuildMI(MBB, MemI, DL, get(Opcode))
4461 .addReg(MemI.getOperand(0).getReg(), getDefRegState(MemI.mayLoad()))
4462 .addReg(AM.BaseReg)
4463 .addReg(OffsetReg)
4465 .addImm(AM.Scale != 1)
4466 .setMemRefs(MemI.memoperands())
4467 .setMIFlags(MemI.getFlags());
4468
4469 return B.getInstr();
4470 }
4471
4473 "Function must not be called with an addressing mode it can't handle");
4474}
4475
4476/// Return true if the opcode is a post-index ld/st instruction, which really
4477/// loads from base+0.
4478static bool isPostIndexLdStOpcode(unsigned Opcode) {
4479 switch (Opcode) {
4480 default:
4481 return false;
4482 case AArch64::LD1Fourv16b_POST:
4483 case AArch64::LD1Fourv1d_POST:
4484 case AArch64::LD1Fourv2d_POST:
4485 case AArch64::LD1Fourv2s_POST:
4486 case AArch64::LD1Fourv4h_POST:
4487 case AArch64::LD1Fourv4s_POST:
4488 case AArch64::LD1Fourv8b_POST:
4489 case AArch64::LD1Fourv8h_POST:
4490 case AArch64::LD1Onev16b_POST:
4491 case AArch64::LD1Onev1d_POST:
4492 case AArch64::LD1Onev2d_POST:
4493 case AArch64::LD1Onev2s_POST:
4494 case AArch64::LD1Onev4h_POST:
4495 case AArch64::LD1Onev4s_POST:
4496 case AArch64::LD1Onev8b_POST:
4497 case AArch64::LD1Onev8h_POST:
4498 case AArch64::LD1Rv16b_POST:
4499 case AArch64::LD1Rv1d_POST:
4500 case AArch64::LD1Rv2d_POST:
4501 case AArch64::LD1Rv2s_POST:
4502 case AArch64::LD1Rv4h_POST:
4503 case AArch64::LD1Rv4s_POST:
4504 case AArch64::LD1Rv8b_POST:
4505 case AArch64::LD1Rv8h_POST:
4506 case AArch64::LD1Threev16b_POST:
4507 case AArch64::LD1Threev1d_POST:
4508 case AArch64::LD1Threev2d_POST:
4509 case AArch64::LD1Threev2s_POST:
4510 case AArch64::LD1Threev4h_POST:
4511 case AArch64::LD1Threev4s_POST:
4512 case AArch64::LD1Threev8b_POST:
4513 case AArch64::LD1Threev8h_POST:
4514 case AArch64::LD1Twov16b_POST:
4515 case AArch64::LD1Twov1d_POST:
4516 case AArch64::LD1Twov2d_POST:
4517 case AArch64::LD1Twov2s_POST:
4518 case AArch64::LD1Twov4h_POST:
4519 case AArch64::LD1Twov4s_POST:
4520 case AArch64::LD1Twov8b_POST:
4521 case AArch64::LD1Twov8h_POST:
4522 case AArch64::LD1i16_POST:
4523 case AArch64::LD1i32_POST:
4524 case AArch64::LD1i64_POST:
4525 case AArch64::LD1i8_POST:
4526 case AArch64::LD2Rv16b_POST:
4527 case AArch64::LD2Rv1d_POST:
4528 case AArch64::LD2Rv2d_POST:
4529 case AArch64::LD2Rv2s_POST:
4530 case AArch64::LD2Rv4h_POST:
4531 case AArch64::LD2Rv4s_POST:
4532 case AArch64::LD2Rv8b_POST:
4533 case AArch64::LD2Rv8h_POST:
4534 case AArch64::LD2Twov16b_POST:
4535 case AArch64::LD2Twov2d_POST:
4536 case AArch64::LD2Twov2s_POST:
4537 case AArch64::LD2Twov4h_POST:
4538 case AArch64::LD2Twov4s_POST:
4539 case AArch64::LD2Twov8b_POST:
4540 case AArch64::LD2Twov8h_POST:
4541 case AArch64::LD2i16_POST:
4542 case AArch64::LD2i32_POST:
4543 case AArch64::LD2i64_POST:
4544 case AArch64::LD2i8_POST:
4545 case AArch64::LD3Rv16b_POST:
4546 case AArch64::LD3Rv1d_POST:
4547 case AArch64::LD3Rv2d_POST:
4548 case AArch64::LD3Rv2s_POST:
4549 case AArch64::LD3Rv4h_POST:
4550 case AArch64::LD3Rv4s_POST:
4551 case AArch64::LD3Rv8b_POST:
4552 case AArch64::LD3Rv8h_POST:
4553 case AArch64::LD3Threev16b_POST:
4554 case AArch64::LD3Threev2d_POST:
4555 case AArch64::LD3Threev2s_POST:
4556 case AArch64::LD3Threev4h_POST:
4557 case AArch64::LD3Threev4s_POST:
4558 case AArch64::LD3Threev8b_POST:
4559 case AArch64::LD3Threev8h_POST:
4560 case AArch64::LD3i16_POST:
4561 case AArch64::LD3i32_POST:
4562 case AArch64::LD3i64_POST:
4563 case AArch64::LD3i8_POST:
4564 case AArch64::LD4Fourv16b_POST:
4565 case AArch64::LD4Fourv2d_POST:
4566 case AArch64::LD4Fourv2s_POST:
4567 case AArch64::LD4Fourv4h_POST:
4568 case AArch64::LD4Fourv4s_POST:
4569 case AArch64::LD4Fourv8b_POST:
4570 case AArch64::LD4Fourv8h_POST:
4571 case AArch64::LD4Rv16b_POST:
4572 case AArch64::LD4Rv1d_POST:
4573 case AArch64::LD4Rv2d_POST:
4574 case AArch64::LD4Rv2s_POST:
4575 case AArch64::LD4Rv4h_POST:
4576 case AArch64::LD4Rv4s_POST:
4577 case AArch64::LD4Rv8b_POST:
4578 case AArch64::LD4Rv8h_POST:
4579 case AArch64::LD4i16_POST:
4580 case AArch64::LD4i32_POST:
4581 case AArch64::LD4i64_POST:
4582 case AArch64::LD4i8_POST:
4583 case AArch64::LDAPRWpost:
4584 case AArch64::LDAPRXpost:
4585 case AArch64::LDIAPPWpost:
4586 case AArch64::LDIAPPXpost:
4587 case AArch64::LDPDpost:
4588 case AArch64::LDPQpost:
4589 case AArch64::LDPSWpost:
4590 case AArch64::LDPSpost:
4591 case AArch64::LDPWpost:
4592 case AArch64::LDPXpost:
4593 case AArch64::LDRBBpost:
4594 case AArch64::LDRBpost:
4595 case AArch64::LDRDpost:
4596 case AArch64::LDRHHpost:
4597 case AArch64::LDRHpost:
4598 case AArch64::LDRQpost:
4599 case AArch64::LDRSBWpost:
4600 case AArch64::LDRSBXpost:
4601 case AArch64::LDRSHWpost:
4602 case AArch64::LDRSHXpost:
4603 case AArch64::LDRSWpost:
4604 case AArch64::LDRSpost:
4605 case AArch64::LDRWpost:
4606 case AArch64::LDRXpost:
4607 case AArch64::ST1Fourv16b_POST:
4608 case AArch64::ST1Fourv1d_POST:
4609 case AArch64::ST1Fourv2d_POST:
4610 case AArch64::ST1Fourv2s_POST:
4611 case AArch64::ST1Fourv4h_POST:
4612 case AArch64::ST1Fourv4s_POST:
4613 case AArch64::ST1Fourv8b_POST:
4614 case AArch64::ST1Fourv8h_POST:
4615 case AArch64::ST1Onev16b_POST:
4616 case AArch64::ST1Onev1d_POST:
4617 case AArch64::ST1Onev2d_POST:
4618 case AArch64::ST1Onev2s_POST:
4619 case AArch64::ST1Onev4h_POST:
4620 case AArch64::ST1Onev4s_POST:
4621 case AArch64::ST1Onev8b_POST:
4622 case AArch64::ST1Onev8h_POST:
4623 case AArch64::ST1Threev16b_POST:
4624 case AArch64::ST1Threev1d_POST:
4625 case AArch64::ST1Threev2d_POST:
4626 case AArch64::ST1Threev2s_POST:
4627 case AArch64::ST1Threev4h_POST:
4628 case AArch64::ST1Threev4s_POST:
4629 case AArch64::ST1Threev8b_POST:
4630 case AArch64::ST1Threev8h_POST:
4631 case AArch64::ST1Twov16b_POST:
4632 case AArch64::ST1Twov1d_POST:
4633 case AArch64::ST1Twov2d_POST:
4634 case AArch64::ST1Twov2s_POST:
4635 case AArch64::ST1Twov4h_POST:
4636 case AArch64::ST1Twov4s_POST:
4637 case AArch64::ST1Twov8b_POST:
4638 case AArch64::ST1Twov8h_POST:
4639 case AArch64::ST1i16_POST:
4640 case AArch64::ST1i32_POST:
4641 case AArch64::ST1i64_POST:
4642 case AArch64::ST1i8_POST:
4643 case AArch64::ST2GPostIndex:
4644 case AArch64::ST2Twov16b_POST:
4645 case AArch64::ST2Twov2d_POST:
4646 case AArch64::ST2Twov2s_POST:
4647 case AArch64::ST2Twov4h_POST:
4648 case AArch64::ST2Twov4s_POST:
4649 case AArch64::ST2Twov8b_POST:
4650 case AArch64::ST2Twov8h_POST:
4651 case AArch64::ST2i16_POST:
4652 case AArch64::ST2i32_POST:
4653 case AArch64::ST2i64_POST:
4654 case AArch64::ST2i8_POST:
4655 case AArch64::ST3Threev16b_POST:
4656 case AArch64::ST3Threev2d_POST:
4657 case AArch64::ST3Threev2s_POST:
4658 case AArch64::ST3Threev4h_POST:
4659 case AArch64::ST3Threev4s_POST:
4660 case AArch64::ST3Threev8b_POST:
4661 case AArch64::ST3Threev8h_POST:
4662 case AArch64::ST3i16_POST:
4663 case AArch64::ST3i32_POST:
4664 case AArch64::ST3i64_POST:
4665 case AArch64::ST3i8_POST:
4666 case AArch64::ST4Fourv16b_POST:
4667 case AArch64::ST4Fourv2d_POST:
4668 case AArch64::ST4Fourv2s_POST:
4669 case AArch64::ST4Fourv4h_POST:
4670 case AArch64::ST4Fourv4s_POST:
4671 case AArch64::ST4Fourv8b_POST:
4672 case AArch64::ST4Fourv8h_POST:
4673 case AArch64::ST4i16_POST:
4674 case AArch64::ST4i32_POST:
4675 case AArch64::ST4i64_POST:
4676 case AArch64::ST4i8_POST:
4677 case AArch64::STGPostIndex:
4678 case AArch64::STGPpost:
4679 case AArch64::STPDpost:
4680 case AArch64::STPQpost:
4681 case AArch64::STPSpost:
4682 case AArch64::STPWpost:
4683 case AArch64::STPXpost:
4684 case AArch64::STRBBpost:
4685 case AArch64::STRBpost:
4686 case AArch64::STRDpost:
4687 case AArch64::STRHHpost:
4688 case AArch64::STRHpost:
4689 case AArch64::STRQpost:
4690 case AArch64::STRSpost:
4691 case AArch64::STRWpost:
4692 case AArch64::STRXpost:
4693 case AArch64::STZ2GPostIndex:
4694 case AArch64::STZGPostIndex:
4695 return true;
4696 }
4697}
4698
4700 const MachineInstr &LdSt, const MachineOperand *&BaseOp, int64_t &Offset,
4701 bool &OffsetIsScalable, TypeSize &Width,
4702 const TargetRegisterInfo *TRI) const {
4703 assert(LdSt.mayLoadOrStore() && "Expected a memory operation.");
4704 // Handle only loads/stores with base register followed by immediate offset.
4705 if (LdSt.getNumExplicitOperands() == 3) {
4706 // Non-paired instruction (e.g., ldr x1, [x0, #8]).
4707 if ((!LdSt.getOperand(1).isReg() && !LdSt.getOperand(1).isFI()) ||
4708 !LdSt.getOperand(2).isImm())
4709 return false;
4710 } else if (LdSt.getNumExplicitOperands() == 4) {
4711 // Paired instruction (e.g., ldp x1, x2, [x0, #8]).
4712 if (!LdSt.getOperand(1).isReg() ||
4713 (!LdSt.getOperand(2).isReg() && !LdSt.getOperand(2).isFI()) ||
4714 !LdSt.getOperand(3).isImm())
4715 return false;
4716 } else
4717 return false;
4718
4719 // Get the scaling factor for the instruction and set the width for the
4720 // instruction.
4721 TypeSize Scale(0U, false);
4722 int64_t Dummy1, Dummy2;
4723
4724 // If this returns false, then it's an instruction we don't want to handle.
4725 if (!getMemOpInfo(LdSt.getOpcode(), Scale, Width, Dummy1, Dummy2))
4726 return false;
4727
4728 // Compute the offset. Offset is calculated as the immediate operand
4729 // multiplied by the scaling factor. Unscaled instructions have scaling factor
4730 // set to 1. Postindex are a special case which have an offset of 0.
4731 if (isPostIndexLdStOpcode(LdSt.getOpcode())) {
4732 BaseOp = &LdSt.getOperand(2);
4733 Offset = 0;
4734 } else if (LdSt.getNumExplicitOperands() == 3) {
4735 BaseOp = &LdSt.getOperand(1);
4736 Offset = LdSt.getOperand(2).getImm() * Scale.getKnownMinValue();
4737 } else {
4738 assert(LdSt.getNumExplicitOperands() == 4 && "invalid number of operands");
4739 BaseOp = &LdSt.getOperand(2);
4740 Offset = LdSt.getOperand(3).getImm() * Scale.getKnownMinValue();
4741 }
4742 OffsetIsScalable = Scale.isScalable();
4743
4744 return BaseOp->isReg() || BaseOp->isFI();
4745}
4746
4749 assert(LdSt.mayLoadOrStore() && "Expected a memory operation.");
4750 MachineOperand &OfsOp = LdSt.getOperand(LdSt.getNumExplicitOperands() - 1);
4751 assert(OfsOp.isImm() && "Offset operand wasn't immediate.");
4752 return OfsOp;
4753}
4754
4755bool AArch64InstrInfo::getMemOpInfo(unsigned Opcode, TypeSize &Scale,
4756 TypeSize &Width, int64_t &MinOffset,
4757 int64_t &MaxOffset) {
4758 switch (Opcode) {
4759 // Not a memory operation or something we want to handle.
4760 default:
4761 Scale = Width = TypeSize::getFixed(0);
4762 MinOffset = MaxOffset = 0;
4763 return false;
4764 // LDR / STR
4765 case AArch64::LDRQui:
4766 case AArch64::STRQui:
4767 Scale = Width = TypeSize::getFixed(16);
4768 MinOffset = 0;
4769 MaxOffset = 4095;
4770 break;
4771 case AArch64::LDRXui:
4772 case AArch64::LDRDui:
4773 case AArch64::STRXui:
4774 case AArch64::STRDui:
4775 case AArch64::PRFMui:
4776 case AArch64::ATOMIC_STORE_HINT_Xui:
4777 case AArch64::ATOMIC_STORE_HINT_Dui:
4778 Scale = Width = TypeSize::getFixed(8);
4779 MinOffset = 0;
4780 MaxOffset = 4095;
4781 break;
4782 case AArch64::LDRWui:
4783 case AArch64::LDRSui:
4784 case AArch64::LDRSWui:
4785 case AArch64::STRWui:
4786 case AArch64::STRSui:
4787 case AArch64::ATOMIC_STORE_HINT_Wui:
4788 case AArch64::ATOMIC_STORE_HINT_Sui:
4789 Scale = Width = TypeSize::getFixed(4);
4790 MinOffset = 0;
4791 MaxOffset = 4095;
4792 break;
4793 case AArch64::LDRHui:
4794 case AArch64::LDRHHui:
4795 case AArch64::LDRSHWui:
4796 case AArch64::LDRSHXui:
4797 case AArch64::STRHui:
4798 case AArch64::STRHHui:
4799 case AArch64::ATOMIC_STORE_HINT_Hui:
4800 Scale = Width = TypeSize::getFixed(2);
4801 MinOffset = 0;
4802 MaxOffset = 4095;
4803 break;
4804 case AArch64::LDRBui:
4805 case AArch64::LDRBBui:
4806 case AArch64::LDRSBWui:
4807 case AArch64::LDRSBXui:
4808 case AArch64::STRBui:
4809 case AArch64::STRBBui:
4810 case AArch64::ATOMIC_STORE_HINT_Bui:
4811 Scale = Width = TypeSize::getFixed(1);
4812 MinOffset = 0;
4813 MaxOffset = 4095;
4814 break;
4815 // post/pre inc
4816 case AArch64::STRQpre:
4817 case AArch64::LDRQpost:
4818 Scale = TypeSize::getFixed(1);
4819 Width = TypeSize::getFixed(16);
4820 MinOffset = -256;
4821 MaxOffset = 255;
4822 break;
4823 case AArch64::LDRDpost:
4824 case AArch64::LDRDpre:
4825 case AArch64::LDRXpost:
4826 case AArch64::LDRXpre:
4827 case AArch64::STRDpost:
4828 case AArch64::STRDpre:
4829 case AArch64::STRXpost:
4830 case AArch64::STRXpre:
4831 Scale = TypeSize::getFixed(1);
4832 Width = TypeSize::getFixed(8);
4833 MinOffset = -256;
4834 MaxOffset = 255;
4835 break;
4836 case AArch64::STRWpost:
4837 case AArch64::STRWpre:
4838 case AArch64::LDRWpost:
4839 case AArch64::LDRWpre:
4840 case AArch64::STRSpost:
4841 case AArch64::STRSpre:
4842 case AArch64::LDRSpost:
4843 case AArch64::LDRSpre:
4844 Scale = TypeSize::getFixed(1);
4845 Width = TypeSize::getFixed(4);
4846 MinOffset = -256;
4847 MaxOffset = 255;
4848 break;
4849 case AArch64::LDRHpost:
4850 case AArch64::LDRHpre:
4851 case AArch64::STRHpost:
4852 case AArch64::STRHpre:
4853 case AArch64::LDRHHpost:
4854 case AArch64::LDRHHpre:
4855 case AArch64::STRHHpost:
4856 case AArch64::STRHHpre:
4857 Scale = TypeSize::getFixed(1);
4858 Width = TypeSize::getFixed(2);
4859 MinOffset = -256;
4860 MaxOffset = 255;
4861 break;
4862 case AArch64::LDRBpost:
4863 case AArch64::LDRBpre:
4864 case AArch64::STRBpost:
4865 case AArch64::STRBpre:
4866 case AArch64::LDRBBpost:
4867 case AArch64::LDRBBpre:
4868 case AArch64::STRBBpost:
4869 case AArch64::STRBBpre:
4870 Scale = Width = TypeSize::getFixed(1);
4871 MinOffset = -256;
4872 MaxOffset = 255;
4873 break;
4874 // Unscaled
4875 case AArch64::LDURQi:
4876 case AArch64::STURQi:
4877 Scale = TypeSize::getFixed(1);
4878 Width = TypeSize::getFixed(16);
4879 MinOffset = -256;
4880 MaxOffset = 255;
4881 break;
4882 case AArch64::LDURXi:
4883 case AArch64::LDURDi:
4884 case AArch64::LDAPURXi:
4885 case AArch64::STURXi:
4886 case AArch64::STURDi:
4887 case AArch64::STLURXi:
4888 case AArch64::PRFUMi:
4889 case AArch64::ATOMIC_STORE_HINT_Xi:
4890 case AArch64::ATOMIC_STORE_HINT_Di:
4891 Scale = TypeSize::getFixed(1);
4892 Width = TypeSize::getFixed(8);
4893 MinOffset = -256;
4894 MaxOffset = 255;
4895 break;
4896 case AArch64::LDURWi:
4897 case AArch64::LDURSi:
4898 case AArch64::LDURSWi:
4899 case AArch64::LDAPURi:
4900 case AArch64::LDAPURSWi:
4901 case AArch64::STURWi:
4902 case AArch64::STURSi:
4903 case AArch64::STLURWi:
4904 case AArch64::ATOMIC_STORE_HINT_Wi:
4905 case AArch64::ATOMIC_STORE_HINT_Si:
4906 Scale = TypeSize::getFixed(1);
4907 Width = TypeSize::getFixed(4);
4908 MinOffset = -256;
4909 MaxOffset = 255;
4910 break;
4911 case AArch64::LDURHi:
4912 case AArch64::LDURHHi:
4913 case AArch64::LDURSHXi:
4914 case AArch64::LDURSHWi:
4915 case AArch64::LDAPURHi:
4916 case AArch64::LDAPURSHWi:
4917 case AArch64::LDAPURSHXi:
4918 case AArch64::STURHi:
4919 case AArch64::STURHHi:
4920 case AArch64::STLURHi:
4921 case AArch64::ATOMIC_STORE_HINT_Hi:
4922 Scale = TypeSize::getFixed(1);
4923 Width = TypeSize::getFixed(2);
4924 MinOffset = -256;
4925 MaxOffset = 255;
4926 break;
4927 case AArch64::LDURBi:
4928 case AArch64::LDURBBi:
4929 case AArch64::LDURSBXi:
4930 case AArch64::LDURSBWi:
4931 case AArch64::LDAPURBi:
4932 case AArch64::LDAPURSBWi:
4933 case AArch64::LDAPURSBXi:
4934 case AArch64::STURBi:
4935 case AArch64::STURBBi:
4936 case AArch64::STLURBi:
4937 case AArch64::ATOMIC_STORE_HINT_Bi:
4938 Scale = Width = TypeSize::getFixed(1);
4939 MinOffset = -256;
4940 MaxOffset = 255;
4941 break;
4942 // LDP / STP (including pre/post inc)
4943 case AArch64::LDPQi:
4944 case AArch64::LDNPQi:
4945 case AArch64::STPQi:
4946 case AArch64::STNPQi:
4947 case AArch64::LDPQpost:
4948 case AArch64::LDPQpre:
4949 case AArch64::STPQpost:
4950 case AArch64::STPQpre:
4951 Scale = TypeSize::getFixed(16);
4952 Width = TypeSize::getFixed(16 * 2);
4953 MinOffset = -64;
4954 MaxOffset = 63;
4955 break;
4956 case AArch64::LDPXi:
4957 case AArch64::LDPDi:
4958 case AArch64::LDNPXi:
4959 case AArch64::LDNPDi:
4960 case AArch64::STPXi:
4961 case AArch64::STPDi:
4962 case AArch64::STNPXi:
4963 case AArch64::STNPDi:
4964 case AArch64::LDPDpost:
4965 case AArch64::LDPDpre:
4966 case AArch64::LDPXpost:
4967 case AArch64::LDPXpre:
4968 case AArch64::STPDpost:
4969 case AArch64::STPDpre:
4970 case AArch64::STPXpost:
4971 case AArch64::STPXpre:
4972 Scale = TypeSize::getFixed(8);
4973 Width = TypeSize::getFixed(8 * 2);
4974 MinOffset = -64;
4975 MaxOffset = 63;
4976 break;
4977 case AArch64::LDPWi:
4978 case AArch64::LDPSi:
4979 case AArch64::LDNPWi:
4980 case AArch64::LDNPSi:
4981 case AArch64::STPWi:
4982 case AArch64::STPSi:
4983 case AArch64::STNPWi:
4984 case AArch64::STNPSi:
4985 case AArch64::LDPSpost:
4986 case AArch64::LDPSpre:
4987 case AArch64::LDPWpost:
4988 case AArch64::LDPWpre:
4989 case AArch64::STPSpost:
4990 case AArch64::STPSpre:
4991 case AArch64::STPWpost:
4992 case AArch64::STPWpre:
4993 Scale = TypeSize::getFixed(4);
4994 Width = TypeSize::getFixed(4 * 2);
4995 MinOffset = -64;
4996 MaxOffset = 63;
4997 break;
4998 case AArch64::StoreSwiftAsyncContext:
4999 // Store is an STRXui, but there might be an ADDXri in the expansion too.
5000 Scale = TypeSize::getFixed(1);
5001 Width = TypeSize::getFixed(8);
5002 MinOffset = 0;
5003 MaxOffset = 4095;
5004 break;
5005 case AArch64::ADDG:
5006 Scale = TypeSize::getFixed(16);
5007 Width = TypeSize::getFixed(0);
5008 MinOffset = 0;
5009 MaxOffset = 63;
5010 break;
5011 case AArch64::TAGPstack:
5012 Scale = TypeSize::getFixed(16);
5013 Width = TypeSize::getFixed(0);
5014 // TAGP with a negative offset turns into SUBP, which has a maximum offset
5015 // of 63 (not 64!).
5016 MinOffset = -63;
5017 MaxOffset = 63;
5018 break;
5019 case AArch64::LDG:
5020 case AArch64::STGi:
5021 case AArch64::STGPreIndex:
5022 case AArch64::STGPostIndex:
5023 case AArch64::STZGi:
5024 case AArch64::STZGPreIndex:
5025 case AArch64::STZGPostIndex:
5026 Scale = Width = TypeSize::getFixed(16);
5027 MinOffset = -256;
5028 MaxOffset = 255;
5029 break;
5030 // SVE
5031 case AArch64::STR_ZZZZXI:
5032 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
5033 case AArch64::LDR_ZZZZXI:
5034 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
5035 Scale = TypeSize::getScalable(16);
5036 Width = TypeSize::getScalable(16 * 4);
5037 MinOffset = -256;
5038 MaxOffset = 252;
5039 break;
5040 case AArch64::STR_ZZZXI:
5041 case AArch64::LDR_ZZZXI:
5042 Scale = TypeSize::getScalable(16);
5043 Width = TypeSize::getScalable(16 * 3);
5044 MinOffset = -256;
5045 MaxOffset = 253;
5046 break;
5047 case AArch64::STR_ZZXI:
5048 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
5049 case AArch64::LDR_ZZXI:
5050 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
5051 Scale = TypeSize::getScalable(16);
5052 Width = TypeSize::getScalable(16 * 2);
5053 MinOffset = -256;
5054 MaxOffset = 254;
5055 break;
5056 case AArch64::LDR_PXI:
5057 case AArch64::STR_PXI:
5058 Scale = Width = TypeSize::getScalable(2);
5059 MinOffset = -256;
5060 MaxOffset = 255;
5061 break;
5062 case AArch64::LDR_PPXI:
5063 case AArch64::STR_PPXI:
5064 Scale = TypeSize::getScalable(2);
5065 Width = TypeSize::getScalable(2 * 2);
5066 MinOffset = -256;
5067 MaxOffset = 254;
5068 break;
5069 case AArch64::LDR_ZXI:
5070 case AArch64::STR_ZXI:
5071 Scale = Width = TypeSize::getScalable(16);
5072 MinOffset = -256;
5073 MaxOffset = 255;
5074 break;
5075 case AArch64::LD1B_IMM:
5076 case AArch64::LD1H_IMM:
5077 case AArch64::LD1W_IMM:
5078 case AArch64::LD1D_IMM:
5079 case AArch64::LDNT1B_ZRI:
5080 case AArch64::LDNT1H_ZRI:
5081 case AArch64::LDNT1W_ZRI:
5082 case AArch64::LDNT1D_ZRI:
5083 case AArch64::ST1B_IMM:
5084 case AArch64::ST1H_IMM:
5085 case AArch64::ST1W_IMM:
5086 case AArch64::ST1D_IMM:
5087 case AArch64::STNT1B_ZRI:
5088 case AArch64::STNT1H_ZRI:
5089 case AArch64::STNT1W_ZRI:
5090 case AArch64::STNT1D_ZRI:
5091 case AArch64::LDNF1B_IMM:
5092 case AArch64::LDNF1H_IMM:
5093 case AArch64::LDNF1W_IMM:
5094 case AArch64::LDNF1D_IMM:
5095 // A full vectors worth of data
5096 // Width = mbytes * elements
5097 Scale = Width = TypeSize::getScalable(16);
5098 MinOffset = -8;
5099 MaxOffset = 7;
5100 break;
5101 case AArch64::LD2B_IMM:
5102 case AArch64::LD2H_IMM:
5103 case AArch64::LD2W_IMM:
5104 case AArch64::LD2D_IMM:
5105 case AArch64::ST2B_IMM:
5106 case AArch64::ST2H_IMM:
5107 case AArch64::ST2W_IMM:
5108 case AArch64::ST2D_IMM:
5109 case AArch64::LD1B_2Z_IMM:
5110 case AArch64::LD1B_2Z_STRIDED_IMM:
5111 case AArch64::LD1H_2Z_IMM:
5112 case AArch64::LD1H_2Z_STRIDED_IMM:
5113 case AArch64::LD1W_2Z_IMM:
5114 case AArch64::LD1W_2Z_STRIDED_IMM:
5115 case AArch64::LD1D_2Z_IMM:
5116 case AArch64::LD1D_2Z_STRIDED_IMM:
5117 case AArch64::LD1B_2Z_IMM_PSEUDO:
5118 case AArch64::LD1H_2Z_IMM_PSEUDO:
5119 case AArch64::LD1W_2Z_IMM_PSEUDO:
5120 case AArch64::LD1D_2Z_IMM_PSEUDO:
5121 case AArch64::ST1B_2Z_IMM:
5122 case AArch64::ST1B_2Z_STRIDED_IMM:
5123 case AArch64::ST1H_2Z_IMM:
5124 case AArch64::ST1H_2Z_STRIDED_IMM:
5125 case AArch64::ST1W_2Z_IMM:
5126 case AArch64::ST1W_2Z_STRIDED_IMM:
5127 case AArch64::ST1D_2Z_IMM:
5128 case AArch64::ST1D_2Z_STRIDED_IMM:
5129 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
5130 case AArch64::LDNT1B_2Z_IMM:
5131 case AArch64::LDNT1B_2Z_STRIDED_IMM:
5132 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
5133 case AArch64::LDNT1H_2Z_IMM:
5134 case AArch64::LDNT1H_2Z_STRIDED_IMM:
5135 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
5136 case AArch64::LDNT1W_2Z_IMM:
5137 case AArch64::LDNT1W_2Z_STRIDED_IMM:
5138 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
5139 case AArch64::LDNT1D_2Z_IMM:
5140 case AArch64::LDNT1D_2Z_STRIDED_IMM:
5141 case AArch64::STNT1B_2Z_IMM:
5142 case AArch64::STNT1B_2Z_STRIDED_IMM:
5143 case AArch64::STNT1H_2Z_IMM:
5144 case AArch64::STNT1H_2Z_STRIDED_IMM:
5145 case AArch64::STNT1W_2Z_IMM:
5146 case AArch64::STNT1W_2Z_STRIDED_IMM:
5147 case AArch64::STNT1D_2Z_IMM:
5148 case AArch64::STNT1D_2Z_STRIDED_IMM:
5149 case AArch64::ST1B_2Z_IMM_PSEUDO:
5150 case AArch64::ST1H_2Z_IMM_PSEUDO:
5151 case AArch64::ST1W_2Z_IMM_PSEUDO:
5152 case AArch64::ST1D_2Z_IMM_PSEUDO:
5153 case AArch64::STNT1B_2Z_IMM_PSEUDO:
5154 case AArch64::STNT1H_2Z_IMM_PSEUDO:
5155 case AArch64::STNT1W_2Z_IMM_PSEUDO:
5156 case AArch64::STNT1D_2Z_IMM_PSEUDO:
5157 Scale = Width = TypeSize::getScalable(16 * 2);
5158 MinOffset = -8;
5159 MaxOffset = 7;
5160 break;
5161 case AArch64::LD3B_IMM:
5162 case AArch64::LD3H_IMM:
5163 case AArch64::LD3W_IMM:
5164 case AArch64::LD3D_IMM:
5165 case AArch64::ST3B_IMM:
5166 case AArch64::ST3H_IMM:
5167 case AArch64::ST3W_IMM:
5168 case AArch64::ST3D_IMM:
5169 Scale = Width = TypeSize::getScalable(16 * 3);
5170 MinOffset = -8;
5171 MaxOffset = 7;
5172 break;
5173 case AArch64::LD4B_IMM:
5174 case AArch64::LD4H_IMM:
5175 case AArch64::LD4W_IMM:
5176 case AArch64::LD4D_IMM:
5177 case AArch64::ST4B_IMM:
5178 case AArch64::ST4H_IMM:
5179 case AArch64::ST4W_IMM:
5180 case AArch64::ST4D_IMM:
5181 case AArch64::LD1B_4Z_IMM:
5182 case AArch64::LD1B_4Z_STRIDED_IMM:
5183 case AArch64::LD1H_4Z_IMM:
5184 case AArch64::LD1H_4Z_STRIDED_IMM:
5185 case AArch64::LD1W_4Z_IMM:
5186 case AArch64::LD1W_4Z_STRIDED_IMM:
5187 case AArch64::LD1D_4Z_IMM:
5188 case AArch64::LD1D_4Z_STRIDED_IMM:
5189 case AArch64::LD1B_4Z_IMM_PSEUDO:
5190 case AArch64::LD1H_4Z_IMM_PSEUDO:
5191 case AArch64::LD1W_4Z_IMM_PSEUDO:
5192 case AArch64::LD1D_4Z_IMM_PSEUDO:
5193 case AArch64::ST1B_4Z_IMM:
5194 case AArch64::ST1B_4Z_STRIDED_IMM:
5195 case AArch64::ST1H_4Z_IMM:
5196 case AArch64::ST1H_4Z_STRIDED_IMM:
5197 case AArch64::ST1W_4Z_IMM:
5198 case AArch64::ST1W_4Z_STRIDED_IMM:
5199 case AArch64::ST1D_4Z_IMM:
5200 case AArch64::ST1D_4Z_STRIDED_IMM:
5201 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
5202 case AArch64::LDNT1B_4Z_IMM:
5203 case AArch64::LDNT1B_4Z_STRIDED_IMM:
5204 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
5205 case AArch64::LDNT1H_4Z_IMM:
5206 case AArch64::LDNT1H_4Z_STRIDED_IMM:
5207 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
5208 case AArch64::LDNT1W_4Z_IMM:
5209 case AArch64::LDNT1W_4Z_STRIDED_IMM:
5210 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
5211 case AArch64::LDNT1D_4Z_IMM:
5212 case AArch64::LDNT1D_4Z_STRIDED_IMM:
5213 case AArch64::STNT1B_4Z_IMM:
5214 case AArch64::STNT1B_4Z_STRIDED_IMM:
5215 case AArch64::STNT1H_4Z_IMM:
5216 case AArch64::STNT1H_4Z_STRIDED_IMM:
5217 case AArch64::STNT1W_4Z_IMM:
5218 case AArch64::STNT1W_4Z_STRIDED_IMM:
5219 case AArch64::STNT1D_4Z_IMM:
5220 case AArch64::STNT1D_4Z_STRIDED_IMM:
5221 case AArch64::ST1B_4Z_IMM_PSEUDO:
5222 case AArch64::ST1H_4Z_IMM_PSEUDO:
5223 case AArch64::ST1W_4Z_IMM_PSEUDO:
5224 case AArch64::ST1D_4Z_IMM_PSEUDO:
5225 case AArch64::STNT1B_4Z_IMM_PSEUDO:
5226 case AArch64::STNT1H_4Z_IMM_PSEUDO:
5227 case AArch64::STNT1W_4Z_IMM_PSEUDO:
5228 case AArch64::STNT1D_4Z_IMM_PSEUDO:
5229 Scale = Width = TypeSize::getScalable(16 * 4);
5230 MinOffset = -8;
5231 MaxOffset = 7;
5232 break;
5233 case AArch64::LD1B_H_IMM:
5234 case AArch64::LD1SB_H_IMM:
5235 case AArch64::LD1H_S_IMM:
5236 case AArch64::LD1SH_S_IMM:
5237 case AArch64::LD1W_D_IMM:
5238 case AArch64::LD1SW_D_IMM:
5239 case AArch64::ST1B_H_IMM:
5240 case AArch64::ST1H_S_IMM:
5241 case AArch64::ST1W_D_IMM:
5242 case AArch64::LDNF1B_H_IMM:
5243 case AArch64::LDNF1SB_H_IMM:
5244 case AArch64::LDNF1H_S_IMM:
5245 case AArch64::LDNF1SH_S_IMM:
5246 case AArch64::LDNF1W_D_IMM:
5247 case AArch64::LDNF1SW_D_IMM:
5248 // A half vector worth of data
5249 // Width = mbytes * elements
5250 Scale = Width = TypeSize::getScalable(8);
5251 MinOffset = -8;
5252 MaxOffset = 7;
5253 break;
5254 case AArch64::LD1B_S_IMM:
5255 case AArch64::LD1SB_S_IMM:
5256 case AArch64::LD1H_D_IMM:
5257 case AArch64::LD1SH_D_IMM:
5258 case AArch64::ST1B_S_IMM:
5259 case AArch64::ST1H_D_IMM:
5260 case AArch64::LDNF1B_S_IMM:
5261 case AArch64::LDNF1SB_S_IMM:
5262 case AArch64::LDNF1H_D_IMM:
5263 case AArch64::LDNF1SH_D_IMM:
5264 // A quarter vector worth of data
5265 // Width = mbytes * elements
5266 Scale = Width = TypeSize::getScalable(4);
5267 MinOffset = -8;
5268 MaxOffset = 7;
5269 break;
5270 case AArch64::LD1B_D_IMM:
5271 case AArch64::LD1SB_D_IMM:
5272 case AArch64::ST1B_D_IMM:
5273 case AArch64::LDNF1B_D_IMM:
5274 case AArch64::LDNF1SB_D_IMM:
5275 // A eighth vector worth of data
5276 // Width = mbytes * elements
5277 Scale = Width = TypeSize::getScalable(2);
5278 MinOffset = -8;
5279 MaxOffset = 7;
5280 break;
5281 case AArch64::ST2Gi:
5282 case AArch64::ST2GPreIndex:
5283 case AArch64::ST2GPostIndex:
5284 case AArch64::STZ2Gi:
5285 case AArch64::STZ2GPreIndex:
5286 case AArch64::STZ2GPostIndex:
5287 Scale = TypeSize::getFixed(16);
5288 Width = TypeSize::getFixed(32);
5289 MinOffset = -256;
5290 MaxOffset = 255;
5291 break;
5292 case AArch64::STGPi:
5293 case AArch64::STGPpost:
5294 case AArch64::STGPpre:
5295 Scale = Width = TypeSize::getFixed(16);
5296 MinOffset = -64;
5297 MaxOffset = 63;
5298 break;
5299 case AArch64::LD1RB_IMM:
5300 case AArch64::LD1RB_H_IMM:
5301 case AArch64::LD1RB_S_IMM:
5302 case AArch64::LD1RB_D_IMM:
5303 case AArch64::LD1RSB_H_IMM:
5304 case AArch64::LD1RSB_S_IMM:
5305 case AArch64::LD1RSB_D_IMM:
5306 Scale = Width = TypeSize::getFixed(1);
5307 MinOffset = 0;
5308 MaxOffset = 63;
5309 break;
5310 case AArch64::LD1RH_IMM:
5311 case AArch64::LD1RH_S_IMM:
5312 case AArch64::LD1RH_D_IMM:
5313 case AArch64::LD1RSH_S_IMM:
5314 case AArch64::LD1RSH_D_IMM:
5315 Scale = Width = TypeSize::getFixed(2);
5316 MinOffset = 0;
5317 MaxOffset = 63;
5318 break;
5319 case AArch64::LD1RW_IMM:
5320 case AArch64::LD1RW_D_IMM:
5321 case AArch64::LD1RSW_IMM:
5322 Scale = Width = TypeSize::getFixed(4);
5323 MinOffset = 0;
5324 MaxOffset = 63;
5325 break;
5326 case AArch64::LD1RD_IMM:
5327 Scale = Width = TypeSize::getFixed(8);
5328 MinOffset = 0;
5329 MaxOffset = 63;
5330 break;
5331 }
5332
5333 return true;
5334}
5335
5336// Scaling factor for unscaled load or store.
5338 switch (Opc) {
5339 default:
5340 llvm_unreachable("Opcode has unknown scale!");
5341 case AArch64::LDRBui:
5342 case AArch64::LDRBBui:
5343 case AArch64::LDURBBi:
5344 case AArch64::LDRSBWui:
5345 case AArch64::LDURSBWi:
5346 case AArch64::STRBui:
5347 case AArch64::STRBBui:
5348 case AArch64::STURBBi:
5349 return 1;
5350 case AArch64::LDRHui:
5351 case AArch64::LDRHHui:
5352 case AArch64::LDURHHi:
5353 case AArch64::LDRSHWui:
5354 case AArch64::LDURSHWi:
5355 case AArch64::STRHui:
5356 case AArch64::STRHHui:
5357 case AArch64::STURHHi:
5358 return 2;
5359 case AArch64::LDRSui:
5360 case AArch64::LDURSi:
5361 case AArch64::LDRSpre:
5362 case AArch64::LDRSWui:
5363 case AArch64::LDURSWi:
5364 case AArch64::LDRSWpre:
5365 case AArch64::LDRWpre:
5366 case AArch64::LDRWui:
5367 case AArch64::LDURWi:
5368 case AArch64::STRSui:
5369 case AArch64::STURSi:
5370 case AArch64::STRSpre:
5371 case AArch64::STRWui:
5372 case AArch64::STURWi:
5373 case AArch64::STRWpre:
5374 case AArch64::LDPSi:
5375 case AArch64::LDPSWi:
5376 case AArch64::LDPWi:
5377 case AArch64::STPSi:
5378 case AArch64::STPWi:
5379 return 4;
5380 case AArch64::LDRDui:
5381 case AArch64::LDURDi:
5382 case AArch64::LDRDpre:
5383 case AArch64::LDRXui:
5384 case AArch64::LDURXi:
5385 case AArch64::LDRXpre:
5386 case AArch64::STRDui:
5387 case AArch64::STURDi:
5388 case AArch64::STRDpre:
5389 case AArch64::STRXui:
5390 case AArch64::STURXi:
5391 case AArch64::STRXpre:
5392 case AArch64::LDPDi:
5393 case AArch64::LDPXi:
5394 case AArch64::STPDi:
5395 case AArch64::STPXi:
5396 return 8;
5397 case AArch64::LDRQui:
5398 case AArch64::LDURQi:
5399 case AArch64::STRQui:
5400 case AArch64::STURQi:
5401 case AArch64::STRQpre:
5402 case AArch64::LDPQi:
5403 case AArch64::LDRQpre:
5404 case AArch64::STPQi:
5405 case AArch64::STGi:
5406 case AArch64::STZGi:
5407 case AArch64::ST2Gi:
5408 case AArch64::STZ2Gi:
5409 case AArch64::STGPi:
5410 return 16;
5411 }
5412}
5413
5415 switch (MI.getOpcode()) {
5416 default:
5417 return false;
5418 case AArch64::LDRWpre:
5419 case AArch64::LDRXpre:
5420 case AArch64::LDRSWpre:
5421 case AArch64::LDRSpre:
5422 case AArch64::LDRDpre:
5423 case AArch64::LDRQpre:
5424 return true;
5425 }
5426}
5427
5429 switch (MI.getOpcode()) {
5430 default:
5431 return false;
5432 case AArch64::STRWpre:
5433 case AArch64::STRXpre:
5434 case AArch64::STRSpre:
5435 case AArch64::STRDpre:
5436 case AArch64::STRQpre:
5437 return true;
5438 }
5439}
5440
5442 return isPreLd(MI) || isPreSt(MI);
5443}
5444
5446 switch (MI.getOpcode()) {
5447 default:
5448 return false;
5449 case AArch64::LDURBBi:
5450 case AArch64::LDURHHi:
5451 case AArch64::LDURWi:
5452 case AArch64::LDRBBui:
5453 case AArch64::LDRHHui:
5454 case AArch64::LDRWui:
5455 case AArch64::LDRBBroX:
5456 case AArch64::LDRHHroX:
5457 case AArch64::LDRWroX:
5458 case AArch64::LDRBBroW:
5459 case AArch64::LDRHHroW:
5460 case AArch64::LDRWroW:
5461 return true;
5462 }
5463}
5464
5466 switch (MI.getOpcode()) {
5467 default:
5468 return false;
5469 case AArch64::LDURSBWi:
5470 case AArch64::LDURSHWi:
5471 case AArch64::LDURSBXi:
5472 case AArch64::LDURSHXi:
5473 case AArch64::LDURSWi:
5474 case AArch64::LDRSBWui:
5475 case AArch64::LDRSHWui:
5476 case AArch64::LDRSBXui:
5477 case AArch64::LDRSHXui:
5478 case AArch64::LDRSWui:
5479 case AArch64::LDRSBWroX:
5480 case AArch64::LDRSHWroX:
5481 case AArch64::LDRSBXroX:
5482 case AArch64::LDRSHXroX:
5483 case AArch64::LDRSWroX:
5484 case AArch64::LDRSBWroW:
5485 case AArch64::LDRSHWroW:
5486 case AArch64::LDRSBXroW:
5487 case AArch64::LDRSHXroW:
5488 case AArch64::LDRSWroW:
5489 return true;
5490 }
5491}
5492
5494 switch (MI.getOpcode()) {
5495 default:
5496 return false;
5497 case AArch64::LDPSi:
5498 case AArch64::LDPSWi:
5499 case AArch64::LDPDi:
5500 case AArch64::LDPQi:
5501 case AArch64::LDPWi:
5502 case AArch64::LDPXi:
5503 case AArch64::STPSi:
5504 case AArch64::STPDi:
5505 case AArch64::STPQi:
5506 case AArch64::STPWi:
5507 case AArch64::STPXi:
5508 case AArch64::STGPi:
5509 return true;
5510 }
5511}
5512
5514 assert(MI.mayLoadOrStore() && "Load or store instruction expected");
5515 unsigned Idx =
5517 : 1;
5518 return MI.getOperand(Idx);
5519}
5520
5521const MachineOperand &
5523 assert(MI.mayLoadOrStore() && "Load or store instruction expected");
5524 unsigned Idx =
5526 : 2;
5527 return MI.getOperand(Idx);
5528}
5529
5530const MachineOperand &
5532 switch (MI.getOpcode()) {
5533 default:
5534 llvm_unreachable("Unexpected opcode");
5535 case AArch64::LDRBroX:
5536 case AArch64::LDRBBroX:
5537 case AArch64::LDRSBXroX:
5538 case AArch64::LDRSBWroX:
5539 case AArch64::LDRHroX:
5540 case AArch64::LDRHHroX:
5541 case AArch64::LDRSHXroX:
5542 case AArch64::LDRSHWroX:
5543 case AArch64::LDRWroX:
5544 case AArch64::LDRSroX:
5545 case AArch64::LDRSWroX:
5546 case AArch64::LDRDroX:
5547 case AArch64::LDRXroX:
5548 case AArch64::LDRQroX:
5549 return MI.getOperand(4);
5550 }
5551}
5552
5554 Register Reg) {
5555 if (MI.getParent() == nullptr)
5556 return nullptr;
5557 const MachineFunction *MF = MI.getParent()->getParent();
5558 return MF ? MF->getRegInfo().getRegClassOrNull(Reg) : nullptr;
5559}
5560
5562 auto IsHFPR = [&](const MachineOperand &Op) {
5563 if (!Op.isReg())
5564 return false;
5565 auto Reg = Op.getReg();
5566 if (Reg.isPhysical())
5567 return AArch64::FPR16RegClass.contains(Reg);
5568 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5569 return TRC == &AArch64::FPR16RegClass ||
5570 TRC == &AArch64::FPR16_loRegClass;
5571 };
5572 return llvm::any_of(MI.operands(), IsHFPR);
5573}
5574
5576 auto IsQFPR = [&](const MachineOperand &Op) {
5577 if (!Op.isReg())
5578 return false;
5579 auto Reg = Op.getReg();
5580 if (Reg.isPhysical())
5581 return AArch64::FPR128RegClass.contains(Reg);
5582 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5583 return TRC == &AArch64::FPR128RegClass ||
5584 TRC == &AArch64::FPR128_loRegClass;
5585 };
5586 return llvm::any_of(MI.operands(), IsQFPR);
5587}
5588
5590 switch (MI.getOpcode()) {
5591 case AArch64::BRK:
5592 case AArch64::HLT:
5593 case AArch64::PACIASP:
5594 case AArch64::PACIBSP:
5595 // Implicit BTI behavior.
5596 return true;
5597 case AArch64::PAUTH_PROLOGUE:
5598 // PAUTH_PROLOGUE expands to PACI(A|B)SP.
5599 return true;
5600 case AArch64::HINT: {
5601 unsigned Imm = MI.getOperand(0).getImm();
5602 // Explicit BTI instruction.
5603 if (Imm == 32 || Imm == 34 || Imm == 36 || Imm == 38)
5604 return true;
5605 // PACI(A|B)SP instructions.
5606 if (Imm == 25 || Imm == 27)
5607 return true;
5608 return false;
5609 }
5610 default:
5611 return false;
5612 }
5613}
5614
5616 if (Reg == 0)
5617 return false;
5618 assert(Reg.isPhysical() && "Expected physical register in isFpOrNEON");
5619 return AArch64::FPR128RegClass.contains(Reg) ||
5620 AArch64::FPR64RegClass.contains(Reg) ||
5621 AArch64::FPR32RegClass.contains(Reg) ||
5622 AArch64::FPR16RegClass.contains(Reg) ||
5623 AArch64::FPR8RegClass.contains(Reg);
5624}
5625
5627 auto IsFPR = [&](const MachineOperand &Op) {
5628 if (!Op.isReg())
5629 return false;
5630 auto Reg = Op.getReg();
5631 if (Reg.isPhysical())
5632 return isFpOrNEON(Reg);
5633
5634 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5635 return TRC == &AArch64::FPR128RegClass ||
5636 TRC == &AArch64::FPR128_loRegClass ||
5637 TRC == &AArch64::FPR64RegClass ||
5638 TRC == &AArch64::FPR64_loRegClass ||
5639 TRC == &AArch64::FPR32RegClass || TRC == &AArch64::FPR16RegClass ||
5640 TRC == &AArch64::FPR8RegClass;
5641 };
5642 return llvm::any_of(MI.operands(), IsFPR);
5643}
5644
5645// Scale the unscaled offsets. Returns false if the unscaled offset can't be
5646// scaled.
5647static bool scaleOffset(unsigned Opc, int64_t &Offset) {
5649
5650 // If the byte-offset isn't a multiple of the stride, we can't scale this
5651 // offset.
5652 if (Offset % Scale != 0)
5653 return false;
5654
5655 // Convert the byte-offset used by unscaled into an "element" offset used
5656 // by the scaled pair load/store instructions.
5657 Offset /= Scale;
5658 return true;
5659}
5660
5661static bool canPairLdStOpc(unsigned FirstOpc, unsigned SecondOpc) {
5662 if (FirstOpc == SecondOpc)
5663 return true;
5664 // We can also pair sign-ext and zero-ext instructions.
5665 switch (FirstOpc) {
5666 default:
5667 return false;
5668 case AArch64::STRSui:
5669 case AArch64::STURSi:
5670 return SecondOpc == AArch64::STRSui || SecondOpc == AArch64::STURSi;
5671 case AArch64::STRDui:
5672 case AArch64::STURDi:
5673 return SecondOpc == AArch64::STRDui || SecondOpc == AArch64::STURDi;
5674 case AArch64::STRQui:
5675 case AArch64::STURQi:
5676 return SecondOpc == AArch64::STRQui || SecondOpc == AArch64::STURQi;
5677 case AArch64::STRWui:
5678 case AArch64::STURWi:
5679 return SecondOpc == AArch64::STRWui || SecondOpc == AArch64::STURWi;
5680 case AArch64::STRXui:
5681 case AArch64::STURXi:
5682 return SecondOpc == AArch64::STRXui || SecondOpc == AArch64::STURXi;
5683 case AArch64::LDRSui:
5684 case AArch64::LDURSi:
5685 return SecondOpc == AArch64::LDRSui || SecondOpc == AArch64::LDURSi;
5686 case AArch64::LDRDui:
5687 case AArch64::LDURDi:
5688 return SecondOpc == AArch64::LDRDui || SecondOpc == AArch64::LDURDi;
5689 case AArch64::LDRQui:
5690 case AArch64::LDURQi:
5691 return SecondOpc == AArch64::LDRQui || SecondOpc == AArch64::LDURQi;
5692 case AArch64::LDRWui:
5693 case AArch64::LDURWi:
5694 return SecondOpc == AArch64::LDRSWui || SecondOpc == AArch64::LDURSWi;
5695 case AArch64::LDRSWui:
5696 case AArch64::LDURSWi:
5697 return SecondOpc == AArch64::LDRWui || SecondOpc == AArch64::LDURWi;
5698 case AArch64::LDRXui:
5699 case AArch64::LDURXi:
5700 return SecondOpc == AArch64::LDRXui || SecondOpc == AArch64::LDURXi;
5701 }
5702 // These instructions can't be paired based on their opcodes.
5703 return false;
5704}
5705
5706static bool shouldClusterFI(const MachineFrameInfo &MFI, int FI1,
5707 int64_t Offset1, unsigned Opcode1, int FI2,
5708 int64_t Offset2, unsigned Opcode2) {
5709 // Accesses through fixed stack object frame indices may access a different
5710 // fixed stack slot. Check that the object offsets + offsets match.
5711 if (MFI.isFixedObjectIndex(FI1) && MFI.isFixedObjectIndex(FI2)) {
5712 int64_t ObjectOffset1 = MFI.getObjectOffset(FI1);
5713 int64_t ObjectOffset2 = MFI.getObjectOffset(FI2);
5714 assert(ObjectOffset1 <= ObjectOffset2 && "Object offsets are not ordered.");
5715 // Convert to scaled object offsets.
5716 int Scale1 = AArch64InstrInfo::getMemScale(Opcode1);
5717 if (ObjectOffset1 % Scale1 != 0)
5718 return false;
5719 ObjectOffset1 /= Scale1;
5720 int Scale2 = AArch64InstrInfo::getMemScale(Opcode2);
5721 if (ObjectOffset2 % Scale2 != 0)
5722 return false;
5723 ObjectOffset2 /= Scale2;
5724 ObjectOffset1 += Offset1;
5725 ObjectOffset2 += Offset2;
5726 return ObjectOffset1 + 1 == ObjectOffset2;
5727 }
5728
5729 return FI1 == FI2;
5730}
5731
5732/// Detect opportunities for ldp/stp formation.
5733///
5734/// Only called for LdSt for which getMemOperandWithOffset returns true.
5736 ArrayRef<const MachineOperand *> BaseOps1, int64_t OpOffset1,
5737 bool OffsetIsScalable1, ArrayRef<const MachineOperand *> BaseOps2,
5738 int64_t OpOffset2, bool OffsetIsScalable2, unsigned ClusterSize,
5739 unsigned NumBytes) const {
5740 assert(BaseOps1.size() == 1 && BaseOps2.size() == 1);
5741 const MachineOperand &BaseOp1 = *BaseOps1.front();
5742 const MachineOperand &BaseOp2 = *BaseOps2.front();
5743 const MachineInstr &FirstLdSt = *BaseOp1.getParent();
5744 const MachineInstr &SecondLdSt = *BaseOp2.getParent();
5745 if (BaseOp1.getType() != BaseOp2.getType())
5746 return false;
5747
5748 assert((BaseOp1.isReg() || BaseOp1.isFI()) &&
5749 "Only base registers and frame indices are supported.");
5750
5751 // Check for both base regs and base FI.
5752 if (BaseOp1.isReg() && BaseOp1.getReg() != BaseOp2.getReg())
5753 return false;
5754
5755 // Only cluster up to a single pair.
5756 if (ClusterSize > 2)
5757 return false;
5758
5759 if (!isPairableLdStInst(FirstLdSt) || !isPairableLdStInst(SecondLdSt))
5760 return false;
5761
5762 // Can we pair these instructions based on their opcodes?
5763 unsigned FirstOpc = FirstLdSt.getOpcode();
5764 unsigned SecondOpc = SecondLdSt.getOpcode();
5765 if (!canPairLdStOpc(FirstOpc, SecondOpc))
5766 return false;
5767
5768 // Can't merge volatiles or load/stores that have a hint to avoid pair
5769 // formation, for example.
5770 if (!isCandidateToMergeOrPair(FirstLdSt) ||
5771 !isCandidateToMergeOrPair(SecondLdSt))
5772 return false;
5773
5774 // isCandidateToMergeOrPair guarantees that operand 2 is an immediate.
5775 int64_t Offset1 = FirstLdSt.getOperand(2).getImm();
5776 if (hasUnscaledLdStOffset(FirstOpc) && !scaleOffset(FirstOpc, Offset1))
5777 return false;
5778
5779 int64_t Offset2 = SecondLdSt.getOperand(2).getImm();
5780 if (hasUnscaledLdStOffset(SecondOpc) && !scaleOffset(SecondOpc, Offset2))
5781 return false;
5782
5783 // Pairwise instructions have a 7-bit signed offset field.
5784 if (Offset1 > 63 || Offset1 < -64)
5785 return false;
5786
5787 // The caller should already have ordered First/SecondLdSt by offset.
5788 // Note: except for non-equal frame index bases
5789 if (BaseOp1.isFI()) {
5790 assert((!BaseOp1.isIdenticalTo(BaseOp2) || Offset1 <= Offset2) &&
5791 "Caller should have ordered offsets.");
5792
5793 const MachineFrameInfo &MFI =
5794 FirstLdSt.getParent()->getParent()->getFrameInfo();
5795 return shouldClusterFI(MFI, BaseOp1.getIndex(), Offset1, FirstOpc,
5796 BaseOp2.getIndex(), Offset2, SecondOpc);
5797 }
5798
5799 assert(Offset1 <= Offset2 && "Caller should have ordered offsets.");
5800
5801 return Offset1 + 1 == Offset2;
5802}
5803
5805 MCRegister Reg, unsigned SubIdx,
5806 RegState State,
5807 const TargetRegisterInfo *TRI) {
5808 if (!SubIdx)
5809 return MIB.addReg(Reg, State);
5810
5811 if (Reg.isPhysical())
5812 return MIB.addReg(TRI->getSubReg(Reg, SubIdx), State);
5813 return MIB.addReg(Reg, State, SubIdx);
5814}
5815
5818 const DebugLoc &DL, MCRegister DestReg,
5819 MCRegister SrcReg, bool KillSrc,
5820 ArrayRef<unsigned> Indices) const {
5821 assert(Subtarget.hasNEON() && "Unexpected register copy without NEON");
5823 uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
5824 uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
5825 unsigned NumRegs = Indices.size();
5826 MCRegister DestSubReg = TRI->getSubReg(DestReg, Indices[0]);
5827 assert(!AArch64::PNRRegClass.contains(DestSubReg) &&
5828 "Unexpected predicate tuple copy");
5829 unsigned MaxRegs = AArch64::PPRRegClass.contains(DestSubReg) ? 15 : 31;
5830
5831 int SubReg = 0, End = NumRegs, Incr = 1;
5832 // Copy in reverse if a forward copy will clobber the tuple
5833 if (((DestEncoding - SrcEncoding) & MaxRegs) < NumRegs) {
5834 SubReg = NumRegs - 1;
5835 End = -1;
5836 Incr = -1;
5837 }
5838
5839 for (; SubReg != End; SubReg += Incr) {
5840 DestSubReg = TRI->getSubReg(DestReg, Indices[SubReg]);
5841 MCRegister SrcSubReg = TRI->getSubReg(SrcReg, Indices[SubReg]);
5842 copyPhysRegImpl(MBB, I, DL, DestSubReg, SrcSubReg, KillSrc);
5843 }
5844}
5845
5848 const DebugLoc &DL, MCRegister DestReg,
5849 MCRegister SrcReg, bool KillSrc,
5850 unsigned Opcode, unsigned ZeroReg,
5851 llvm::ArrayRef<unsigned> Indices) const {
5853 unsigned NumRegs = Indices.size();
5854
5855#ifndef NDEBUG
5856 uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
5857 uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
5858 assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 &&
5859 "GPR reg sequences should not be able to overlap");
5860#endif
5861
5862 for (unsigned SubReg = 0; SubReg != NumRegs; ++SubReg) {
5863 const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode));
5864 AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI);
5865 MIB.addReg(ZeroReg);
5866 AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI);
5867 MIB.addImm(0);
5868 }
5869}
5870
5871/// Returns true if the instruction at I is in a streaming call site region,
5872/// within a single basic block.
5873/// A "call site streaming region" starts after smstart and ends at smstop
5874/// around a call to a streaming function. This walks backward from I.
5877 MachineFunction &MF = *MBB.getParent();
5879 if (!AFI->hasStreamingModeChanges())
5880 return false;
5881 // Walk backwards to find smstart/smstop
5882 for (MachineInstr &MI : reverse(make_range(MBB.begin(), I))) {
5883 unsigned Opc = MI.getOpcode();
5884 if (Opc == AArch64::MSRpstatesvcrImm1 || Opc == AArch64::MSRpstatePseudo) {
5885 // Check if this is SM change (not ZA)
5886 int64_t PState = MI.getOperand(0).getImm();
5887 if (PState == AArch64SVCR::SVCRSM || PState == AArch64SVCR::SVCRSMZA) {
5888 // Operand 1 is 1 for start, 0 for stop
5889 return MI.getOperand(1).getImm() == 1;
5890 }
5891 }
5892 }
5893 return false;
5894}
5895
5896/// Returns true if in a streaming call site region without SME-FA64.
5897static bool mustAvoidNeonAtMBBI(const AArch64Subtarget &Subtarget,
5900 return !Subtarget.hasSMEFA64() && isInStreamingCallSiteRegion(MBB, I);
5901}
5902
5905 const DebugLoc &DL, Register DestReg,
5906 Register SrcReg, bool KillSrc,
5907 bool RenamableDest,
5908 bool RenamableSrc) const {
5909 if (AArch64::GPR32spRegClass.contains(DestReg) &&
5910 AArch64::GPR32spRegClass.contains(SrcReg)) {
5911 if (DestReg == AArch64::WSP || SrcReg == AArch64::WSP) {
5912 // If either operand is WSP, expand to ADD #0.
5913 if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5914 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5915 // Cyclone recognizes "ADD Xd, Xn, #0" as a zero-cycle register move.
5916 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5917 &AArch64::GPR64spRegClass);
5918 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5919 &AArch64::GPR64spRegClass);
5920 // This instruction is reading and writing X registers. This may upset
5921 // the register scavenger and machine verifier, so we need to indicate
5922 // that we are reading an undefined value from SrcRegX, but a proper
5923 // value from SrcReg.
5924 BuildMI(MBB, I, DL, get(AArch64::ADDXri), DestRegX)
5925 .addReg(SrcRegX, RegState::Undef)
5926 .addImm(0)
5928 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
5929 ++NumZCRegMoveInstrsGPR;
5930 } else {
5931 BuildMI(MBB, I, DL, get(AArch64::ADDWri), DestReg)
5932 .addReg(SrcReg, getKillRegState(KillSrc))
5933 .addImm(0)
5935 if (Subtarget.hasZeroCycleRegMoveGPR32())
5936 ++NumZCRegMoveInstrsGPR;
5937 }
5938 } else if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5939 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5940 // Cyclone recognizes "ORR Xd, XZR, Xm" as a zero-cycle register move.
5941 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5942 &AArch64::GPR64spRegClass);
5943 assert(DestRegX.isValid() && "Destination super-reg not valid");
5944 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5945 &AArch64::GPR64spRegClass);
5946 assert(SrcRegX.isValid() && "Source super-reg not valid");
5947 // This instruction is reading and writing X registers. This may upset
5948 // the register scavenger and machine verifier, so we need to indicate
5949 // that we are reading an undefined value from SrcRegX, but a proper
5950 // value from SrcReg.
5951 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestRegX)
5952 .addReg(AArch64::XZR)
5953 .addReg(SrcRegX, RegState::Undef)
5954 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
5955 ++NumZCRegMoveInstrsGPR;
5956 } else {
5957 // Otherwise, expand to ORR WZR.
5958 BuildMI(MBB, I, DL, get(AArch64::ORRWrr), DestReg)
5959 .addReg(AArch64::WZR)
5960 .addReg(SrcReg, getKillRegState(KillSrc));
5961 if (Subtarget.hasZeroCycleRegMoveGPR32())
5962 ++NumZCRegMoveInstrsGPR;
5963 }
5964 return;
5965 }
5966
5967 // GPR32 zeroing
5968 if (AArch64::GPR32spRegClass.contains(DestReg) && SrcReg == AArch64::WZR) {
5969 if (Subtarget.hasZeroCycleZeroingGPR64() &&
5970 !Subtarget.hasZeroCycleZeroingGPR32()) {
5971 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5972 &AArch64::GPR64spRegClass);
5973 assert(DestRegX.isValid() && "Destination super-reg not valid");
5974 BuildMI(MBB, I, DL, get(AArch64::MOVZXi), DestRegX)
5975 .addImm(0)
5977 ++NumZCZeroingInstrsGPR;
5978 } else if (Subtarget.hasZeroCycleZeroingGPR32()) {
5979 BuildMI(MBB, I, DL, get(AArch64::MOVZWi), DestReg)
5980 .addImm(0)
5982 ++NumZCZeroingInstrsGPR;
5983 } else {
5984 BuildMI(MBB, I, DL, get(AArch64::ORRWrr), DestReg)
5985 .addReg(AArch64::WZR)
5986 .addReg(AArch64::WZR);
5987 }
5988 return;
5989 }
5990
5991 if (AArch64::GPR64spRegClass.contains(DestReg) &&
5992 AArch64::GPR64spRegClass.contains(SrcReg)) {
5993 if (DestReg == AArch64::SP || SrcReg == AArch64::SP) {
5994 // If either operand is SP, expand to ADD #0.
5995 BuildMI(MBB, I, DL, get(AArch64::ADDXri), DestReg)
5996 .addReg(SrcReg, getKillRegState(KillSrc))
5997 .addImm(0)
5999 if (Subtarget.hasZeroCycleRegMoveGPR64())
6000 ++NumZCRegMoveInstrsGPR;
6001 } else {
6002 // Otherwise, expand to ORR XZR.
6003 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestReg)
6004 .addReg(AArch64::XZR)
6005 .addReg(SrcReg, getKillRegState(KillSrc));
6006 if (Subtarget.hasZeroCycleRegMoveGPR64())
6007 ++NumZCRegMoveInstrsGPR;
6008 }
6009 return;
6010 }
6011
6012 // GPR64 zeroing
6013 if (AArch64::GPR64spRegClass.contains(DestReg) && SrcReg == AArch64::XZR) {
6014 if (Subtarget.hasZeroCycleZeroingGPR64()) {
6015 BuildMI(MBB, I, DL, get(AArch64::MOVZXi), DestReg)
6016 .addImm(0)
6018 ++NumZCZeroingInstrsGPR;
6019 } else {
6020 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestReg)
6021 .addReg(AArch64::XZR)
6022 .addReg(AArch64::XZR);
6023 }
6024 return;
6025 }
6026
6027 // Copy a Predicate register by ORRing with itself.
6028 if (AArch64::PPRRegClass.contains(DestReg) &&
6029 AArch64::PPRRegClass.contains(SrcReg)) {
6030 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6031 "Unexpected SVE register.");
6032 BuildMI(MBB, I, DL, get(AArch64::ORR_PPzPP), DestReg)
6033 .addReg(SrcReg) // Pg
6034 .addReg(SrcReg)
6035 .addReg(SrcReg, getKillRegState(KillSrc));
6036 return;
6037 }
6038
6039 // Copy a predicate-as-counter register by ORRing with itself as if it
6040 // were a regular predicate (mask) register.
6041 bool DestIsPNR = AArch64::PNRRegClass.contains(DestReg);
6042 bool SrcIsPNR = AArch64::PNRRegClass.contains(SrcReg);
6043 if (DestIsPNR || SrcIsPNR) {
6044 auto ToPPR = [](MCRegister R) -> MCRegister {
6045 return (R - AArch64::PN0) + AArch64::P0;
6046 };
6047 MCRegister PPRSrcReg = SrcIsPNR ? ToPPR(SrcReg) : SrcReg.asMCReg();
6048 MCRegister PPRDestReg = DestIsPNR ? ToPPR(DestReg) : DestReg.asMCReg();
6049
6050 if (PPRSrcReg != PPRDestReg) {
6051 auto NewMI = BuildMI(MBB, I, DL, get(AArch64::ORR_PPzPP), PPRDestReg)
6052 .addReg(PPRSrcReg) // Pg
6053 .addReg(PPRSrcReg)
6054 .addReg(PPRSrcReg, getKillRegState(KillSrc));
6055 if (DestIsPNR)
6056 NewMI.addDef(DestReg, RegState::Implicit);
6057 }
6058 return;
6059 }
6060
6061 // Copy a predicate register pair by copying the individual sub-registers.
6062 if (AArch64::PPR2RegClass.contains(DestReg) &&
6063 AArch64::PPR2RegClass.contains(SrcReg)) {
6064 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6065 "Unexpected SVE predicate register.");
6066 static const unsigned Indices[] = {AArch64::psub0, AArch64::psub1};
6067 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6068 return;
6069 }
6070
6071 // Copy a Z register by ORRing with itself.
6072 if (AArch64::ZPRRegClass.contains(DestReg) &&
6073 AArch64::ZPRRegClass.contains(SrcReg)) {
6074 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6075 "Unexpected SVE register.");
6076 BuildMI(MBB, I, DL, get(AArch64::ORR_ZZZ), DestReg)
6077 .addReg(SrcReg)
6078 .addReg(SrcReg, getKillRegState(KillSrc));
6079 return;
6080 }
6081
6082 // Copy a Z register pair by copying the individual sub-registers.
6083 if ((AArch64::ZPR2RegClass.contains(DestReg) ||
6084 AArch64::ZPR2StridedOrContiguousRegClass.contains(DestReg)) &&
6085 (AArch64::ZPR2RegClass.contains(SrcReg) ||
6086 AArch64::ZPR2StridedOrContiguousRegClass.contains(SrcReg))) {
6087 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6088 "Unexpected SVE register.");
6089 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1};
6090 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6091 return;
6092 }
6093
6094 // Copy a Z register triple by copying the individual sub-registers.
6095 if (AArch64::ZPR3RegClass.contains(DestReg) &&
6096 AArch64::ZPR3RegClass.contains(SrcReg)) {
6097 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6098 "Unexpected SVE register.");
6099 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
6100 AArch64::zsub2};
6101 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6102 return;
6103 }
6104
6105 // Copy a Z register quad by copying the individual sub-registers.
6106 if ((AArch64::ZPR4RegClass.contains(DestReg) ||
6107 AArch64::ZPR4StridedOrContiguousRegClass.contains(DestReg)) &&
6108 (AArch64::ZPR4RegClass.contains(SrcReg) ||
6109 AArch64::ZPR4StridedOrContiguousRegClass.contains(SrcReg))) {
6110 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6111 "Unexpected SVE register.");
6112 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
6113 AArch64::zsub2, AArch64::zsub3};
6114 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6115 return;
6116 }
6117
6118 // Copy a DDDD register quad by copying the individual sub-registers.
6119 if (AArch64::DDDDRegClass.contains(DestReg) &&
6120 AArch64::DDDDRegClass.contains(SrcReg)) {
6121 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
6122 AArch64::dsub2, AArch64::dsub3};
6123 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6124 return;
6125 }
6126
6127 // Copy a DDD register triple by copying the individual sub-registers.
6128 if (AArch64::DDDRegClass.contains(DestReg) &&
6129 AArch64::DDDRegClass.contains(SrcReg)) {
6130 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
6131 AArch64::dsub2};
6132 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6133 return;
6134 }
6135
6136 // Copy a DD register pair by copying the individual sub-registers.
6137 if (AArch64::DDRegClass.contains(DestReg) &&
6138 AArch64::DDRegClass.contains(SrcReg)) {
6139 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1};
6140 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6141 return;
6142 }
6143
6144 // Copy a QQQQ register quad by copying the individual sub-registers.
6145 if (AArch64::QQQQRegClass.contains(DestReg) &&
6146 AArch64::QQQQRegClass.contains(SrcReg)) {
6147 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
6148 AArch64::qsub2, AArch64::qsub3};
6149 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6150 return;
6151 }
6152
6153 // Copy a QQQ register triple by copying the individual sub-registers.
6154 if (AArch64::QQQRegClass.contains(DestReg) &&
6155 AArch64::QQQRegClass.contains(SrcReg)) {
6156 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
6157 AArch64::qsub2};
6158 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6159 return;
6160 }
6161
6162 // Copy a QQ register pair by copying the individual sub-registers.
6163 if (AArch64::QQRegClass.contains(DestReg) &&
6164 AArch64::QQRegClass.contains(SrcReg)) {
6165 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1};
6166 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6167 return;
6168 }
6169
6170 if (AArch64::XSeqPairsClassRegClass.contains(DestReg) &&
6171 AArch64::XSeqPairsClassRegClass.contains(SrcReg)) {
6172 static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64};
6173 copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRXrs,
6174 AArch64::XZR, Indices);
6175 return;
6176 }
6177
6178 if (AArch64::WSeqPairsClassRegClass.contains(DestReg) &&
6179 AArch64::WSeqPairsClassRegClass.contains(SrcReg)) {
6180 static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32};
6181 copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRWrs,
6182 AArch64::WZR, Indices);
6183 return;
6184 }
6185
6186 if (AArch64::FPR128RegClass.contains(DestReg) &&
6187 AArch64::FPR128RegClass.contains(SrcReg)) {
6188 // In streaming regions, NEON is illegal but streaming-SVE is available.
6189 // Use SVE for copies if we're in a streaming region and SME is available.
6190 // With +sme-fa64, NEON is legal in streaming mode so we can use it.
6191 if ((Subtarget.isSVEorStreamingSVEAvailable() &&
6192 !Subtarget.isNeonAvailable()) ||
6193 mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6194 BuildMI(MBB, I, DL, get(AArch64::ORR_ZZZ))
6195 .addReg(AArch64::Z0 + (DestReg - AArch64::Q0), RegState::Define)
6196 .addReg(AArch64::Z0 + (SrcReg - AArch64::Q0))
6197 .addReg(AArch64::Z0 + (SrcReg - AArch64::Q0));
6198 } else if (Subtarget.isNeonAvailable()) {
6199 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
6200 .addReg(SrcReg)
6201 .addReg(SrcReg, getKillRegState(KillSrc));
6202 if (Subtarget.hasZeroCycleRegMoveFPR128())
6203 ++NumZCRegMoveInstrsFPR;
6204 } else {
6205 BuildMI(MBB, I, DL, get(AArch64::STRQpre))
6206 .addReg(AArch64::SP, RegState::Define)
6207 .addReg(SrcReg, getKillRegState(KillSrc))
6208 .addReg(AArch64::SP)
6209 .addImm(-16);
6210 BuildMI(MBB, I, DL, get(AArch64::LDRQpost))
6211 .addReg(AArch64::SP, RegState::Define)
6212 .addReg(DestReg, RegState::Define)
6213 .addReg(AArch64::SP)
6214 .addImm(16);
6215 }
6216 return;
6217 }
6218
6219 if (AArch64::FPR64RegClass.contains(DestReg) &&
6220 AArch64::FPR64RegClass.contains(SrcReg)) {
6221 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6222 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6223 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6224 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6225 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::dsub,
6226 &AArch64::FPR128RegClass);
6227 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::dsub,
6228 &AArch64::FPR128RegClass);
6229 // This instruction is reading and writing Q registers. This may upset
6230 // the register scavenger and machine verifier, so we need to indicate
6231 // that we are reading an undefined value from SrcRegQ, but a proper
6232 // value from SrcReg.
6233 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6234 .addReg(SrcRegQ, RegState::Undef)
6235 .addReg(SrcRegQ, RegState::Undef)
6236 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6237 ++NumZCRegMoveInstrsFPR;
6238 } else {
6239 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestReg)
6240 .addReg(SrcReg, getKillRegState(KillSrc));
6241 if (Subtarget.hasZeroCycleRegMoveFPR64())
6242 ++NumZCRegMoveInstrsFPR;
6243 }
6244 return;
6245 }
6246
6247 if (AArch64::FPR32RegClass.contains(DestReg) &&
6248 AArch64::FPR32RegClass.contains(SrcReg)) {
6249 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6250 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6251 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6252 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6253 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
6254 &AArch64::FPR128RegClass);
6255 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
6256 &AArch64::FPR128RegClass);
6257 // This instruction is reading and writing Q registers. This may upset
6258 // the register scavenger and machine verifier, so we need to indicate
6259 // that we are reading an undefined value from SrcRegQ, but a proper
6260 // value from SrcReg.
6261 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6262 .addReg(SrcRegQ, RegState::Undef)
6263 .addReg(SrcRegQ, RegState::Undef)
6264 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6265 ++NumZCRegMoveInstrsFPR;
6266 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6267 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6268 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
6269 &AArch64::FPR64RegClass);
6270 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
6271 &AArch64::FPR64RegClass);
6272 // This instruction is reading and writing D registers. This may upset
6273 // the register scavenger and machine verifier, so we need to indicate
6274 // that we are reading an undefined value from SrcRegD, but a proper
6275 // value from SrcReg.
6276 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6277 .addReg(SrcRegD, RegState::Undef)
6278 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6279 ++NumZCRegMoveInstrsFPR;
6280 } else {
6281 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6282 .addReg(SrcReg, getKillRegState(KillSrc));
6283 if (Subtarget.hasZeroCycleRegMoveFPR32())
6284 ++NumZCRegMoveInstrsFPR;
6285 }
6286 return;
6287 }
6288
6289 if (AArch64::FPR16RegClass.contains(DestReg) &&
6290 AArch64::FPR16RegClass.contains(SrcReg)) {
6291 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6292 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6293 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6294 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6295 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6296 &AArch64::FPR128RegClass);
6297 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6298 &AArch64::FPR128RegClass);
6299 // This instruction is reading and writing Q registers. This may upset
6300 // the register scavenger and machine verifier, so we need to indicate
6301 // that we are reading an undefined value from SrcRegQ, but a proper
6302 // value from SrcReg.
6303 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6304 .addReg(SrcRegQ, RegState::Undef)
6305 .addReg(SrcRegQ, RegState::Undef)
6306 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6307 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6308 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6309 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6310 &AArch64::FPR64RegClass);
6311 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6312 &AArch64::FPR64RegClass);
6313 // This instruction is reading and writing D registers. This may upset
6314 // the register scavenger and machine verifier, so we need to indicate
6315 // that we are reading an undefined value from SrcRegD, but a proper
6316 // value from SrcReg.
6317 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6318 .addReg(SrcRegD, RegState::Undef)
6319 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6320 } else {
6321 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6322 &AArch64::FPR32RegClass);
6323 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6324 &AArch64::FPR32RegClass);
6325 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6326 .addReg(SrcReg, getKillRegState(KillSrc));
6327 }
6328 return;
6329 }
6330
6331 if (AArch64::FPR8RegClass.contains(DestReg) &&
6332 AArch64::FPR8RegClass.contains(SrcReg)) {
6333 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6334 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6335 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6336 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6337 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6338 &AArch64::FPR128RegClass);
6339 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6340 &AArch64::FPR128RegClass);
6341 // This instruction is reading and writing Q registers. This may upset
6342 // the register scavenger and machine verifier, so we need to indicate
6343 // that we are reading an undefined value from SrcRegQ, but a proper
6344 // value from SrcReg.
6345 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6346 .addReg(SrcRegQ, RegState::Undef)
6347 .addReg(SrcRegQ, RegState::Undef)
6348 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6349 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6350 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6351 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6352 &AArch64::FPR64RegClass);
6353 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6354 &AArch64::FPR64RegClass);
6355 // This instruction is reading and writing D registers. This may upset
6356 // the register scavenger and machine verifier, so we need to indicate
6357 // that we are reading an undefined value from SrcRegD, but a proper
6358 // value from SrcReg.
6359 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6360 .addReg(SrcRegD, RegState::Undef)
6361 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6362 } else {
6363 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6364 &AArch64::FPR32RegClass);
6365 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6366 &AArch64::FPR32RegClass);
6367 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6368 .addReg(SrcReg, getKillRegState(KillSrc));
6369 }
6370 return;
6371 }
6372
6373 // Copies between GPR64 and FPR64.
6374 if (AArch64::FPR64RegClass.contains(DestReg) &&
6375 AArch64::GPR64RegClass.contains(SrcReg)) {
6376 if (AArch64::XZR == SrcReg) {
6377 BuildMI(MBB, I, DL, get(AArch64::FMOVD0), DestReg);
6378 } else {
6379 BuildMI(MBB, I, DL, get(AArch64::FMOVXDr), DestReg)
6380 .addReg(SrcReg, getKillRegState(KillSrc));
6381 }
6382 return;
6383 }
6384 if (AArch64::GPR64RegClass.contains(DestReg) &&
6385 AArch64::FPR64RegClass.contains(SrcReg)) {
6386 BuildMI(MBB, I, DL, get(AArch64::FMOVDXr), DestReg)
6387 .addReg(SrcReg, getKillRegState(KillSrc));
6388 return;
6389 }
6390 // Copies between GPR32 and FPR32.
6391 if (AArch64::FPR32RegClass.contains(DestReg) &&
6392 AArch64::GPR32RegClass.contains(SrcReg)) {
6393 if (AArch64::WZR == SrcReg) {
6394 BuildMI(MBB, I, DL, get(AArch64::FMOVS0), DestReg);
6395 } else {
6396 BuildMI(MBB, I, DL, get(AArch64::FMOVWSr), DestReg)
6397 .addReg(SrcReg, getKillRegState(KillSrc));
6398 }
6399 return;
6400 }
6401 if (AArch64::GPR32RegClass.contains(DestReg) &&
6402 AArch64::FPR32RegClass.contains(SrcReg)) {
6403 BuildMI(MBB, I, DL, get(AArch64::FMOVSWr), DestReg)
6404 .addReg(SrcReg, getKillRegState(KillSrc));
6405 return;
6406 }
6407
6408 if (DestReg == AArch64::NZCV) {
6409 assert(AArch64::GPR64RegClass.contains(SrcReg) && "Invalid NZCV copy");
6410 BuildMI(MBB, I, DL, get(AArch64::MSR))
6411 .addImm(AArch64SysReg::NZCV)
6412 .addReg(SrcReg, getKillRegState(KillSrc))
6413 .addReg(AArch64::NZCV, RegState::Implicit | RegState::Define);
6414 return;
6415 }
6416
6417 if (SrcReg == AArch64::NZCV) {
6418 assert(AArch64::GPR64RegClass.contains(DestReg) && "Invalid NZCV copy");
6419 BuildMI(MBB, I, DL, get(AArch64::MRS), DestReg)
6420 .addImm(AArch64SysReg::NZCV)
6421 .addReg(AArch64::NZCV, RegState::Implicit | getKillRegState(KillSrc));
6422 return;
6423 }
6424
6425#ifndef NDEBUG
6426 errs() << RI.getRegAsmName(DestReg) << " = COPY " << RI.getRegAsmName(SrcReg)
6427 << "\n";
6428#endif
6429 llvm_unreachable("unimplemented reg-to-reg copy");
6430}
6431
6434 const DebugLoc &DL, Register DestReg,
6435 Register SrcReg, bool KillSrc,
6436 bool RenamableDest,
6437 bool RenamableSrc) const {
6438 ++NumCopyInstrs;
6439 copyPhysRegImpl(MBB, I, DL, DestReg, SrcReg, KillSrc, RenamableDest,
6440 RenamableSrc);
6441 return;
6442}
6443
6446 MachineBasicBlock::iterator InsertBefore,
6447 const MCInstrDesc &MCID,
6448 Register SrcReg, bool IsKill,
6449 unsigned SubIdx0, unsigned SubIdx1, int FI,
6450 MachineMemOperand *MMO) {
6451 Register SrcReg0 = SrcReg;
6452 Register SrcReg1 = SrcReg;
6453 if (SrcReg.isPhysical()) {
6454 SrcReg0 = TRI.getSubReg(SrcReg, SubIdx0);
6455 SubIdx0 = 0;
6456 SrcReg1 = TRI.getSubReg(SrcReg, SubIdx1);
6457 SubIdx1 = 0;
6458 }
6459 BuildMI(MBB, InsertBefore, DebugLoc(), MCID)
6460 .addReg(SrcReg0, getKillRegState(IsKill), SubIdx0)
6461 .addReg(SrcReg1, getKillRegState(IsKill), SubIdx1)
6462 .addFrameIndex(FI)
6463 .addImm(0)
6464 .addMemOperand(MMO);
6465}
6466
6469 Register SrcReg, bool isKill, int FI,
6470 const TargetRegisterClass *RC,
6471 Register VReg,
6472 MachineInstr::MIFlag Flags) const {
6473 MachineFunction &MF = *MBB.getParent();
6474 MachineFrameInfo &MFI = MF.getFrameInfo();
6475
6477 MachineMemOperand *MMO =
6479 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
6480 unsigned Opc = 0;
6481 bool Offset = true;
6483 unsigned StackID = TargetStackID::Default;
6484 switch (RI.getSpillSize(*RC)) {
6485 case 1:
6486 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6487 Opc = AArch64::STRBui;
6488 break;
6489 case 2: {
6490 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6491 Opc = AArch64::STRHui;
6492 else if (AArch64::PNRRegClass.hasSubClassEq(RC) ||
6493 AArch64::PPRRegClass.hasSubClassEq(RC)) {
6494 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6495 "Unexpected register store without SVE store instructions");
6496 Opc = AArch64::STR_PXI;
6498 }
6499 break;
6500 }
6501 case 4:
6502 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6503 Opc = AArch64::STRWui;
6504 if (SrcReg.isVirtual())
6505 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR32RegClass);
6506 else
6507 assert(SrcReg != AArch64::WSP);
6508 } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6509 Opc = AArch64::STRSui;
6510 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6511 Opc = AArch64::STR_PPXI;
6513 }
6514 break;
6515 case 8:
6516 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6517 Opc = AArch64::STRXui;
6518 if (SrcReg.isVirtual())
6519 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
6520 else
6521 assert(SrcReg != AArch64::SP);
6522 } else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6523 Opc = AArch64::STRDui;
6524 } else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6526 get(AArch64::STPWi), SrcReg, isKill,
6527 AArch64::sube32, AArch64::subo32, FI, MMO);
6528 return;
6529 }
6530 break;
6531 case 16:
6532 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6533 Opc = AArch64::STRQui;
6534 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6535 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6536 Opc = AArch64::ST1Twov1d;
6537 Offset = false;
6538 } else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6540 get(AArch64::STPXi), SrcReg, isKill,
6541 AArch64::sube64, AArch64::subo64, FI, MMO);
6542 return;
6543 } else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6544 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6545 "Unexpected register store without SVE store instructions");
6546 Opc = AArch64::STR_ZXI;
6548 }
6549 break;
6550 case 24:
6551 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6552 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6553 Opc = AArch64::ST1Threev1d;
6554 Offset = false;
6555 }
6556 break;
6557 case 32:
6558 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6559 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6560 Opc = AArch64::ST1Fourv1d;
6561 Offset = false;
6562 } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6563 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6564 Opc = AArch64::ST1Twov2d;
6565 Offset = false;
6566 } else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6567 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6568 "Unexpected register store without SVE store instructions");
6569 Opc = AArch64::STR_ZZXI_STRIDED_CONTIGUOUS;
6571 } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6572 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6573 "Unexpected register store without SVE store instructions");
6574 Opc = AArch64::STR_ZZXI;
6576 }
6577 break;
6578 case 48:
6579 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6580 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6581 Opc = AArch64::ST1Threev2d;
6582 Offset = false;
6583 } else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6584 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6585 "Unexpected register store without SVE store instructions");
6586 Opc = AArch64::STR_ZZZXI;
6588 }
6589 break;
6590 case 64:
6591 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6592 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6593 Opc = AArch64::ST1Fourv2d;
6594 Offset = false;
6595 } else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6596 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6597 "Unexpected register store without SVE store instructions");
6598 Opc = AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS;
6600 } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6601 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6602 "Unexpected register store without SVE store instructions");
6603 Opc = AArch64::STR_ZZZZXI;
6605 }
6606 break;
6607 }
6608 assert(Opc && "Unknown register class");
6609 MFI.setStackID(FI, StackID);
6610
6612 .addReg(SrcReg, getKillRegState(isKill))
6613 .addFrameIndex(FI);
6614
6615 if (Offset)
6616 MI.addImm(0);
6617 if (PNRReg.isValid())
6618 MI.addDef(PNRReg, RegState::Implicit);
6619 MI.addMemOperand(MMO);
6620}
6621
6624 MachineBasicBlock::iterator InsertBefore,
6625 const MCInstrDesc &MCID,
6626 Register DestReg, unsigned SubIdx0,
6627 unsigned SubIdx1, int FI,
6628 MachineMemOperand *MMO) {
6629 Register DestReg0 = DestReg;
6630 Register DestReg1 = DestReg;
6631 bool IsUndef = true;
6632 if (DestReg.isPhysical()) {
6633 DestReg0 = TRI.getSubReg(DestReg, SubIdx0);
6634 SubIdx0 = 0;
6635 DestReg1 = TRI.getSubReg(DestReg, SubIdx1);
6636 SubIdx1 = 0;
6637 IsUndef = false;
6638 }
6639 BuildMI(MBB, InsertBefore, DebugLoc(), MCID)
6640 .addReg(DestReg0, RegState::Define | getUndefRegState(IsUndef), SubIdx0)
6641 .addReg(DestReg1, RegState::Define | getUndefRegState(IsUndef), SubIdx1)
6642 .addFrameIndex(FI)
6643 .addImm(0)
6644 .addMemOperand(MMO);
6645}
6646
6649 Register DestReg, int FI,
6650 const TargetRegisterClass *RC,
6651 Register VReg, unsigned SubReg,
6652 MachineInstr::MIFlag Flags) const {
6653 MachineFunction &MF = *MBB.getParent();
6654 MachineFrameInfo &MFI = MF.getFrameInfo();
6656 MachineMemOperand *MMO =
6658 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
6659
6660 unsigned Opc = 0;
6661 bool Offset = true;
6662 unsigned StackID = TargetStackID::Default;
6663 Register PNRReg;
6664 switch (TRI.getSpillSize(*RC)) {
6665 case 1:
6666 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6667 Opc = AArch64::LDRBui;
6668 break;
6669 case 2: {
6670 bool IsPNR = AArch64::PNRRegClass.hasSubClassEq(RC);
6671 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6672 Opc = AArch64::LDRHui;
6673 else if (IsPNR || AArch64::PPRRegClass.hasSubClassEq(RC)) {
6674 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6675 "Unexpected register load without SVE load instructions");
6676 if (IsPNR)
6677 PNRReg = DestReg;
6678 Opc = AArch64::LDR_PXI;
6680 }
6681 break;
6682 }
6683 case 4:
6684 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6685 Opc = AArch64::LDRWui;
6686 if (DestReg.isVirtual())
6687 MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR32RegClass);
6688 else
6689 assert(DestReg != AArch64::WSP);
6690 } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6691 Opc = AArch64::LDRSui;
6692 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6693 Opc = AArch64::LDR_PPXI;
6695 }
6696 break;
6697 case 8:
6698 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6699 Opc = AArch64::LDRXui;
6700 if (DestReg.isVirtual())
6701 MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR64RegClass);
6702 else
6703 assert(DestReg != AArch64::SP);
6704 } else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6705 Opc = AArch64::LDRDui;
6706 } else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6708 get(AArch64::LDPWi), DestReg, AArch64::sube32,
6709 AArch64::subo32, FI, MMO);
6710 return;
6711 }
6712 break;
6713 case 16:
6714 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6715 Opc = AArch64::LDRQui;
6716 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6717 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6718 Opc = AArch64::LD1Twov1d;
6719 Offset = false;
6720 } else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6722 get(AArch64::LDPXi), DestReg, AArch64::sube64,
6723 AArch64::subo64, FI, MMO);
6724 return;
6725 } else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6726 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6727 "Unexpected register load without SVE load instructions");
6728 Opc = AArch64::LDR_ZXI;
6730 }
6731 break;
6732 case 24:
6733 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6734 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6735 Opc = AArch64::LD1Threev1d;
6736 Offset = false;
6737 }
6738 break;
6739 case 32:
6740 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6741 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6742 Opc = AArch64::LD1Fourv1d;
6743 Offset = false;
6744 } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6745 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6746 Opc = AArch64::LD1Twov2d;
6747 Offset = false;
6748 } else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6749 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6750 "Unexpected register load without SVE load instructions");
6751 Opc = AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS;
6753 } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6754 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6755 "Unexpected register load without SVE load instructions");
6756 Opc = AArch64::LDR_ZZXI;
6758 }
6759 break;
6760 case 48:
6761 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6762 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6763 Opc = AArch64::LD1Threev2d;
6764 Offset = false;
6765 } else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6766 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6767 "Unexpected register load without SVE load instructions");
6768 Opc = AArch64::LDR_ZZZXI;
6770 }
6771 break;
6772 case 64:
6773 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6774 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6775 Opc = AArch64::LD1Fourv2d;
6776 Offset = false;
6777 } else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6778 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6779 "Unexpected register load without SVE load instructions");
6780 Opc = AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS;
6782 } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6783 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6784 "Unexpected register load without SVE load instructions");
6785 Opc = AArch64::LDR_ZZZZXI;
6787 }
6788 break;
6789 }
6790
6791 assert(Opc && "Unknown register class");
6792 MFI.setStackID(FI, StackID);
6793
6795 .addReg(DestReg, getDefRegState(true))
6796 .addFrameIndex(FI);
6797 if (Offset)
6798 MI.addImm(0);
6799 if (PNRReg.isValid() && !PNRReg.isVirtual())
6800 MI.addDef(PNRReg, RegState::Implicit);
6801 MI.addMemOperand(MMO);
6802}
6803
6805 const MachineInstr &UseMI,
6806 const TargetRegisterInfo *TRI) {
6807 return any_of(instructionsWithoutDebug(std::next(DefMI.getIterator()),
6808 UseMI.getIterator()),
6809 [TRI](const MachineInstr &I) {
6810 return I.modifiesRegister(AArch64::NZCV, TRI) ||
6811 I.readsRegister(AArch64::NZCV, TRI);
6812 });
6813}
6814
6815void AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6816 const StackOffset &Offset, int64_t &ByteSized, int64_t &VGSized) {
6817 // The smallest scalable element supported by scaled SVE addressing
6818 // modes are predicates, which are 2 scalable bytes in size. So the scalable
6819 // byte offset must always be a multiple of 2.
6820 assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
6821
6822 // VGSized offsets are divided by '2', because the VG register is the
6823 // the number of 64bit granules as opposed to 128bit vector chunks,
6824 // which is how the 'n' in e.g. MVT::nxv1i8 is modelled.
6825 // So, for a stack offset of 16 MVT::nxv1i8's, the size is n x 16 bytes.
6826 // VG = n * 2 and the dwarf offset must be VG * 8 bytes.
6827 ByteSized = Offset.getFixed();
6828 VGSized = Offset.getScalable() / 2;
6829}
6830
6831/// Returns the offset in parts to which this frame offset can be
6832/// decomposed for the purpose of describing a frame offset.
6833/// For non-scalable offsets this is simply its byte size.
6834void AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
6835 const StackOffset &Offset, int64_t &NumBytes, int64_t &NumPredicateVectors,
6836 int64_t &NumDataVectors) {
6837 // The smallest scalable element supported by scaled SVE addressing
6838 // modes are predicates, which are 2 scalable bytes in size. So the scalable
6839 // byte offset must always be a multiple of 2.
6840 assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
6841
6842 NumBytes = Offset.getFixed();
6843 NumDataVectors = 0;
6844 NumPredicateVectors = Offset.getScalable() / 2;
6845 // This method is used to get the offsets to adjust the frame offset.
6846 // If the function requires ADDPL to be used and needs more than two ADDPL
6847 // instructions, part of the offset is folded into NumDataVectors so that it
6848 // uses ADDVL for part of it, reducing the number of ADDPL instructions.
6849 if (NumPredicateVectors % 8 == 0 || NumPredicateVectors < -64 ||
6850 NumPredicateVectors > 62) {
6851 NumDataVectors = NumPredicateVectors / 8;
6852 NumPredicateVectors -= NumDataVectors * 8;
6853 }
6854}
6855
6856// Convenience function to create a DWARF expression for: Constant `Operation`.
6857// This helper emits compact sequences for common cases. For example, for`-15
6858// DW_OP_plus`, this helper would create DW_OP_lit15 DW_OP_minus.
6861 if (Operation == dwarf::DW_OP_plus && Constant < 0 && -Constant <= 31) {
6862 // -Constant (1 to 31)
6863 Expr.push_back(dwarf::DW_OP_lit0 - Constant);
6864 Operation = dwarf::DW_OP_minus;
6865 } else if (Constant >= 0 && Constant <= 31) {
6866 // Literal value 0 to 31
6867 Expr.push_back(dwarf::DW_OP_lit0 + Constant);
6868 } else {
6869 // Signed constant
6870 Expr.push_back(dwarf::DW_OP_consts);
6872 }
6873 return Expr.push_back(Operation);
6874}
6875
6876// Convenience function to create a DWARF expression for a register.
6877static void appendReadRegExpr(SmallVectorImpl<char> &Expr, unsigned RegNum) {
6878 Expr.push_back((char)dwarf::DW_OP_bregx);
6880 Expr.push_back(0);
6881}
6882
6883// Convenience function to create a DWARF expression for loading a register from
6884// a CFA offset.
6886 int64_t OffsetFromDefCFA) {
6887 // This assumes the top of the DWARF stack contains the CFA.
6888 Expr.push_back(dwarf::DW_OP_dup);
6889 // Add the offset to the register.
6890 appendConstantExpr(Expr, OffsetFromDefCFA, dwarf::DW_OP_plus);
6891 // Dereference the address (loads a 64 bit value)..
6892 Expr.push_back(dwarf::DW_OP_deref);
6893}
6894
6895// Convenience function to create a comment for
6896// (+/-) NumBytes (* RegScale)?
6897static void appendOffsetComment(int NumBytes, llvm::raw_string_ostream &Comment,
6898 StringRef RegScale = {}) {
6899 if (NumBytes) {
6900 Comment << (NumBytes < 0 ? " - " : " + ") << std::abs(NumBytes);
6901 if (!RegScale.empty())
6902 Comment << ' ' << RegScale;
6903 }
6904}
6905
6906// Creates an MCCFIInstruction:
6907// { DW_CFA_def_cfa_expression, ULEB128 (sizeof expr), expr }
6909 unsigned Reg,
6910 const StackOffset &Offset) {
6911 int64_t NumBytes, NumVGScaledBytes;
6912 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(Offset, NumBytes,
6913 NumVGScaledBytes);
6914 std::string CommentBuffer;
6915 llvm::raw_string_ostream Comment(CommentBuffer);
6916
6917 if (Reg == AArch64::SP)
6918 Comment << "sp";
6919 else if (Reg == AArch64::FP)
6920 Comment << "fp";
6921 else
6922 Comment << printReg(Reg, &TRI);
6923
6924 // Build up the expression (Reg + NumBytes + VG * NumVGScaledBytes)
6925 SmallString<64> Expr;
6926 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6927 assert(DwarfReg <= 31 && "DwarfReg out of bounds (0..31)");
6928 // Reg + NumBytes
6929 Expr.push_back(dwarf::DW_OP_breg0 + DwarfReg);
6930 appendLEB128<LEB128Sign::Signed>(Expr, NumBytes);
6931 appendOffsetComment(NumBytes, Comment);
6932 if (NumVGScaledBytes) {
6933 // + VG * NumVGScaledBytes
6934 appendOffsetComment(NumVGScaledBytes, Comment, "* VG");
6935 appendReadRegExpr(Expr, TRI.getDwarfRegNum(AArch64::VG, true));
6936 appendConstantExpr(Expr, NumVGScaledBytes, dwarf::DW_OP_mul);
6937 Expr.push_back(dwarf::DW_OP_plus);
6938 }
6939
6940 // Wrap this into DW_CFA_def_cfa.
6941 SmallString<64> DefCfaExpr;
6942 DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression);
6943 appendLEB128<LEB128Sign::Unsigned>(DefCfaExpr, Expr.size());
6944 DefCfaExpr.append(Expr.str());
6945 return MCCFIInstruction::createEscape(nullptr, DefCfaExpr.str(), SMLoc(),
6946 Comment.str());
6947}
6948
6950 unsigned FrameReg, unsigned Reg,
6951 const StackOffset &Offset,
6952 bool LastAdjustmentWasScalable) {
6953 if (Offset.getScalable())
6954 return createDefCFAExpression(TRI, Reg, Offset);
6955
6956 if (FrameReg == Reg && !LastAdjustmentWasScalable)
6957 return MCCFIInstruction::cfiDefCfaOffset(nullptr, int(Offset.getFixed()));
6958
6959 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6960 return MCCFIInstruction::cfiDefCfa(nullptr, DwarfReg, (int)Offset.getFixed());
6961}
6962
6965 const StackOffset &OffsetFromDefCFA,
6966 std::optional<int64_t> IncomingVGOffsetFromDefCFA) {
6967 int64_t NumBytes, NumVGScaledBytes;
6968 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6969 OffsetFromDefCFA, NumBytes, NumVGScaledBytes);
6970
6971 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6972
6973 // Non-scalable offsets can use DW_CFA_offset directly.
6974 if (!NumVGScaledBytes)
6975 return MCCFIInstruction::createOffset(nullptr, DwarfReg, NumBytes);
6976
6977 std::string CommentBuffer;
6978 llvm::raw_string_ostream Comment(CommentBuffer);
6979 Comment << printReg(Reg, &TRI) << " @ cfa";
6980
6981 // Build up expression (CFA + VG * NumVGScaledBytes + NumBytes)
6982 assert(NumVGScaledBytes && "Expected scalable offset");
6983 SmallString<64> OffsetExpr;
6984 // + VG * NumVGScaledBytes
6985 StringRef VGRegScale;
6986 if (IncomingVGOffsetFromDefCFA) {
6987 appendLoadRegExpr(OffsetExpr, *IncomingVGOffsetFromDefCFA);
6988 VGRegScale = "* IncomingVG";
6989 } else {
6990 appendReadRegExpr(OffsetExpr, TRI.getDwarfRegNum(AArch64::VG, true));
6991 VGRegScale = "* VG";
6992 }
6993 appendConstantExpr(OffsetExpr, NumVGScaledBytes, dwarf::DW_OP_mul);
6994 appendOffsetComment(NumVGScaledBytes, Comment, VGRegScale);
6995 OffsetExpr.push_back(dwarf::DW_OP_plus);
6996 if (NumBytes) {
6997 // + NumBytes
6998 appendOffsetComment(NumBytes, Comment);
6999 appendConstantExpr(OffsetExpr, NumBytes, dwarf::DW_OP_plus);
7000 }
7001
7002 // Wrap this into DW_CFA_expression
7003 SmallString<64> CfaExpr;
7004 CfaExpr.push_back(dwarf::DW_CFA_expression);
7005 appendLEB128<LEB128Sign::Unsigned>(CfaExpr, DwarfReg);
7006 appendLEB128<LEB128Sign::Unsigned>(CfaExpr, OffsetExpr.size());
7007 CfaExpr.append(OffsetExpr.str());
7008
7009 return MCCFIInstruction::createEscape(nullptr, CfaExpr.str(), SMLoc(),
7010 Comment.str());
7011}
7012
7013// Helper function to emit a frame offset adjustment from a given
7014// pointer (SrcReg), stored into DestReg. This function is explicit
7015// in that it requires the opcode.
7018 const DebugLoc &DL, unsigned DestReg,
7019 unsigned SrcReg, int64_t Offset, unsigned Opc,
7020 const TargetInstrInfo *TII,
7021 MachineInstr::MIFlag Flag, bool NeedsWinCFI,
7022 bool *HasWinCFI, bool EmitCFAOffset,
7023 StackOffset CFAOffset, unsigned FrameReg) {
7024 int Sign = 1;
7025 unsigned MaxEncoding, ShiftSize;
7026 switch (Opc) {
7027 case AArch64::ADDXri:
7028 case AArch64::ADDSXri:
7029 case AArch64::SUBXri:
7030 case AArch64::SUBSXri:
7031 MaxEncoding = 0xfff;
7032 ShiftSize = 12;
7033 break;
7034 case AArch64::ADDVL_XXI:
7035 case AArch64::ADDPL_XXI:
7036 case AArch64::ADDSVL_XXI:
7037 case AArch64::ADDSPL_XXI:
7038 MaxEncoding = 31;
7039 ShiftSize = 0;
7040 if (Offset < 0) {
7041 MaxEncoding = 32;
7042 Sign = -1;
7043 Offset = -Offset;
7044 }
7045 break;
7046 default:
7047 llvm_unreachable("Unsupported opcode");
7048 }
7049
7050 // `Offset` can be in bytes or in "scalable bytes".
7051 int VScale = 1;
7052 if (Opc == AArch64::ADDVL_XXI || Opc == AArch64::ADDSVL_XXI)
7053 VScale = 16;
7054 else if (Opc == AArch64::ADDPL_XXI || Opc == AArch64::ADDSPL_XXI)
7055 VScale = 2;
7056
7057 // FIXME: If the offset won't fit in 24-bits, compute the offset into a
7058 // scratch register. If DestReg is a virtual register, use it as the
7059 // scratch register; otherwise, create a new virtual register (to be
7060 // replaced by the scavenger at the end of PEI). That case can be optimized
7061 // slightly if DestReg is SP which is always 16-byte aligned, so the scratch
7062 // register can be loaded with offset%8 and the add/sub can use an extending
7063 // instruction with LSL#3.
7064 // Currently the function handles any offsets but generates a poor sequence
7065 // of code.
7066 // assert(Offset < (1 << 24) && "unimplemented reg plus immediate");
7067
7068 const unsigned MaxEncodableValue = MaxEncoding << ShiftSize;
7069 Register TmpReg = DestReg;
7070 if (TmpReg == AArch64::XZR)
7071 TmpReg = MBB.getParent()->getRegInfo().createVirtualRegister(
7072 &AArch64::GPR64RegClass);
7073 do {
7074 uint64_t ThisVal = std::min<uint64_t>(Offset, MaxEncodableValue);
7075 unsigned LocalShiftSize = 0;
7076 if (ThisVal > MaxEncoding) {
7077 ThisVal = ThisVal >> ShiftSize;
7078 LocalShiftSize = ShiftSize;
7079 }
7080 assert((ThisVal >> ShiftSize) <= MaxEncoding &&
7081 "Encoding cannot handle value that big");
7082
7083 Offset -= ThisVal << LocalShiftSize;
7084 if (Offset == 0)
7085 TmpReg = DestReg;
7086 auto MBI = BuildMI(MBB, MBBI, DL, TII->get(Opc), TmpReg)
7087 .addReg(SrcReg)
7088 .addImm(Sign * (int)ThisVal);
7089 if (ShiftSize)
7090 MBI = MBI.addImm(
7092 MBI = MBI.setMIFlag(Flag);
7093
7094 auto Change =
7095 VScale == 1
7096 ? StackOffset::getFixed(ThisVal << LocalShiftSize)
7097 : StackOffset::getScalable(VScale * (ThisVal << LocalShiftSize));
7098 if (Sign == -1 || Opc == AArch64::SUBXri || Opc == AArch64::SUBSXri)
7099 CFAOffset += Change;
7100 else
7101 CFAOffset -= Change;
7102 if (EmitCFAOffset && DestReg == TmpReg) {
7103 MachineFunction &MF = *MBB.getParent();
7104 const TargetSubtargetInfo &STI = MF.getSubtarget();
7105 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
7106
7107 unsigned CFIIndex = MF.addFrameInst(
7108 createDefCFA(TRI, FrameReg, DestReg, CFAOffset, VScale != 1));
7109 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
7110 .addCFIIndex(CFIIndex)
7111 .setMIFlags(Flag);
7112 }
7113
7114 if (NeedsWinCFI) {
7115 int Imm = (int)(ThisVal << LocalShiftSize);
7116 if (VScale != 1 && DestReg == AArch64::SP) {
7117 if (HasWinCFI)
7118 *HasWinCFI = true;
7119 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AllocZ))
7120 .addImm(ThisVal)
7121 .setMIFlag(Flag);
7122 } else if ((DestReg == AArch64::FP && SrcReg == AArch64::SP) ||
7123 (SrcReg == AArch64::FP && DestReg == AArch64::SP)) {
7124 assert(VScale == 1 && "Expected non-scalable operation");
7125 if (HasWinCFI)
7126 *HasWinCFI = true;
7127 if (Imm == 0)
7128 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_SetFP)).setMIFlag(Flag);
7129 else
7130 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AddFP))
7131 .addImm(Imm)
7132 .setMIFlag(Flag);
7133 assert(Offset == 0 && "Expected remaining offset to be zero to "
7134 "emit a single SEH directive");
7135 } else if (DestReg == AArch64::SP) {
7136 assert(VScale == 1 && "Expected non-scalable operation");
7137 if (HasWinCFI)
7138 *HasWinCFI = true;
7139 assert(SrcReg == AArch64::SP && "Unexpected SrcReg for SEH_StackAlloc");
7140 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc))
7141 .addImm(Imm)
7142 .setMIFlag(Flag);
7143 }
7144 }
7145
7146 SrcReg = TmpReg;
7147 } while (Offset);
7148}
7149
7152 unsigned DestReg, unsigned SrcReg,
7154 MachineInstr::MIFlag Flag, bool SetNZCV,
7155 bool NeedsWinCFI, bool *HasWinCFI,
7156 bool EmitCFAOffset, StackOffset CFAOffset,
7157 unsigned FrameReg) {
7158 // If a function is marked as arm_locally_streaming, then the runtime value of
7159 // vscale in the prologue/epilogue is different the runtime value of vscale
7160 // in the function's body. To avoid having to consider multiple vscales,
7161 // we can use `addsvl` to allocate any scalable stack-slots, which under
7162 // most circumstances will be only locals, not callee-save slots.
7163 const Function &F = MBB.getParent()->getFunction();
7164 bool UseSVL = F.hasFnAttribute("aarch64_pstate_sm_body");
7165
7166 int64_t Bytes, NumPredicateVectors, NumDataVectors;
7167 AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
7168 Offset, Bytes, NumPredicateVectors, NumDataVectors);
7169
7170 // Insert ADDSXri for scalable offset at the end.
7171 bool NeedsFinalDefNZCV = SetNZCV && (NumPredicateVectors || NumDataVectors);
7172 if (NeedsFinalDefNZCV)
7173 SetNZCV = false;
7174
7175 // First emit non-scalable frame offsets, or a simple 'mov'.
7176 if (Bytes || (!Offset && SrcReg != DestReg)) {
7177 assert((DestReg != AArch64::SP || Bytes % 8 == 0) &&
7178 "SP increment/decrement not 8-byte aligned");
7179 unsigned Opc = SetNZCV ? AArch64::ADDSXri : AArch64::ADDXri;
7180 if (Bytes < 0) {
7181 Bytes = -Bytes;
7182 Opc = SetNZCV ? AArch64::SUBSXri : AArch64::SUBXri;
7183 }
7184 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, Bytes, Opc, TII, Flag,
7185 NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7186 FrameReg);
7187 CFAOffset += (Opc == AArch64::ADDXri || Opc == AArch64::ADDSXri)
7188 ? StackOffset::getFixed(-Bytes)
7189 : StackOffset::getFixed(Bytes);
7190 SrcReg = DestReg;
7191 FrameReg = DestReg;
7192 }
7193
7194 assert(!(NeedsWinCFI && NumPredicateVectors) &&
7195 "WinCFI can't allocate fractions of an SVE data vector");
7196
7197 if (NumDataVectors) {
7198 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, NumDataVectors,
7199 UseSVL ? AArch64::ADDSVL_XXI : AArch64::ADDVL_XXI, TII,
7200 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7201 FrameReg);
7202 CFAOffset += StackOffset::getScalable(-NumDataVectors * 16);
7203 SrcReg = DestReg;
7204 }
7205
7206 if (NumPredicateVectors) {
7207 assert(DestReg != AArch64::SP && "Unaligned access to SP");
7208 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, NumPredicateVectors,
7209 UseSVL ? AArch64::ADDSPL_XXI : AArch64::ADDPL_XXI, TII,
7210 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7211 FrameReg);
7212 }
7213
7214 if (NeedsFinalDefNZCV)
7215 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDSXri), DestReg)
7216 .addReg(DestReg)
7217 .addImm(0)
7218 .addImm(0);
7219}
7220
7223 int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS,
7224 VirtRegMap *VRM) const {
7226 // This is a bit of a hack. Consider this instruction:
7227 //
7228 // %0 = COPY %sp; GPR64all:%0
7229 //
7230 // We explicitly chose GPR64all for the virtual register so such a copy might
7231 // be eliminated by RegisterCoalescer. However, that may not be possible, and
7232 // %0 may even spill. We can't spill %sp, and since it is in the GPR64all
7233 // register class, TargetInstrInfo::foldMemoryOperand() is going to try.
7234 //
7235 // To prevent that, we are going to constrain the %0 register class here.
7236 if (MI.isFullCopy()) {
7237 Register DstReg = MI.getOperand(0).getReg();
7238 Register SrcReg = MI.getOperand(1).getReg();
7239 if (SrcReg == AArch64::SP && DstReg.isVirtual()) {
7240 MF.getRegInfo().constrainRegClass(DstReg, &AArch64::GPR64RegClass);
7241 return nullptr;
7242 }
7243 if (DstReg == AArch64::SP && SrcReg.isVirtual()) {
7244 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
7245 return nullptr;
7246 }
7247 // Nothing can folded with copy from/to NZCV.
7248 if (SrcReg == AArch64::NZCV || DstReg == AArch64::NZCV)
7249 return nullptr;
7250 }
7251
7252 // Handle the case where a copy is being spilled or filled but the source
7253 // and destination register class don't match. For example:
7254 //
7255 // %0 = COPY %xzr; GPR64common:%0
7256 //
7257 // In this case we can still safely fold away the COPY and generate the
7258 // following spill code:
7259 //
7260 // STRXui %xzr, %stack.0
7261 //
7262 // This also eliminates spilled cross register class COPYs (e.g. between x and
7263 // d regs) of the same size. For example:
7264 //
7265 // %0 = COPY %1; GPR64:%0, FPR64:%1
7266 //
7267 // will be filled as
7268 //
7269 // LDRDui %0, fi<#0>
7270 //
7271 // instead of
7272 //
7273 // LDRXui %Temp, fi<#0>
7274 // %0 = FMOV %Temp
7275 //
7276 if (MI.isCopy() && Ops.size() == 1 &&
7277 // Make sure we're only folding the explicit COPY defs/uses.
7278 (Ops[0] == 0 || Ops[0] == 1)) {
7279 bool IsSpill = Ops[0] == 0;
7280 bool IsFill = !IsSpill;
7282 const MachineRegisterInfo &MRI = MF.getRegInfo();
7283 MachineBasicBlock &MBB = *MI.getParent();
7284 const MachineOperand &DstMO = MI.getOperand(0);
7285 const MachineOperand &SrcMO = MI.getOperand(1);
7286 Register DstReg = DstMO.getReg();
7287 Register SrcReg = SrcMO.getReg();
7288 // This is slightly expensive to compute for physical regs since
7289 // getMinimalPhysRegClass is slow.
7290 auto getRegClass = [&](unsigned Reg) {
7291 return Register::isVirtualRegister(Reg) ? MRI.getRegClass(Reg)
7292 : TRI.getMinimalPhysRegClass(Reg);
7293 };
7294
7295 if (DstMO.getSubReg() == 0 && SrcMO.getSubReg() == 0) {
7296 assert(TRI.getRegSizeInBits(*getRegClass(DstReg)) ==
7297 TRI.getRegSizeInBits(*getRegClass(SrcReg)) &&
7298 "Mismatched register size in non subreg COPY");
7299 if (IsSpill)
7300 storeRegToStackSlot(MBB, InsertPt, SrcReg, SrcMO.isKill(), FrameIndex,
7301 getRegClass(SrcReg), Register());
7302 else
7303 loadRegFromStackSlot(MBB, InsertPt, DstReg, FrameIndex,
7304 getRegClass(DstReg), Register());
7305 return &*--InsertPt;
7306 }
7307
7308 // Handle cases like spilling def of:
7309 //
7310 // %0:sub_32<def,read-undef> = COPY %wzr; GPR64common:%0
7311 //
7312 // where the physical register source can be widened and stored to the full
7313 // virtual reg destination stack slot, in this case producing:
7314 //
7315 // STRXui %xzr, %stack.0
7316 //
7317 if (IsSpill && DstMO.isUndef() && SrcReg == AArch64::WZR &&
7318 TRI.getRegSizeInBits(*getRegClass(DstReg)) == 64) {
7319 assert(SrcMO.getSubReg() == 0 &&
7320 "Unexpected subreg on physical register");
7321 storeRegToStackSlot(MBB, InsertPt, AArch64::XZR, SrcMO.isKill(),
7322 FrameIndex, &AArch64::GPR64RegClass, Register());
7323 return &*--InsertPt;
7324 }
7325
7326 // Handle cases like filling use of:
7327 //
7328 // %0:sub_32<def,read-undef> = COPY %1; GPR64:%0, GPR32:%1
7329 //
7330 // where we can load the full virtual reg source stack slot, into the subreg
7331 // destination, in this case producing:
7332 //
7333 // LDRWui %0:sub_32<def,read-undef>, %stack.0
7334 //
7335 if (IsFill && SrcMO.getSubReg() == 0 && DstMO.isUndef()) {
7336 const TargetRegisterClass *FillRC = nullptr;
7337 switch (DstMO.getSubReg()) {
7338 default:
7339 break;
7340 case AArch64::sub_32:
7341 if (AArch64::GPR64RegClass.hasSubClassEq(getRegClass(DstReg)))
7342 FillRC = &AArch64::GPR32RegClass;
7343 break;
7344 case AArch64::ssub:
7345 FillRC = &AArch64::FPR32RegClass;
7346 break;
7347 case AArch64::dsub:
7348 FillRC = &AArch64::FPR64RegClass;
7349 break;
7350 }
7351
7352 if (FillRC) {
7353 assert(TRI.getRegSizeInBits(*getRegClass(SrcReg)) ==
7354 TRI.getRegSizeInBits(*FillRC) &&
7355 "Mismatched regclass size on folded subreg COPY");
7356 loadRegFromStackSlot(MBB, InsertPt, DstReg, FrameIndex, FillRC,
7357 Register());
7358 MachineInstr &LoadMI = *--InsertPt;
7359 MachineOperand &LoadDst = LoadMI.getOperand(0);
7360 assert(LoadDst.getSubReg() == 0 && "unexpected subreg on fill load");
7361 LoadDst.setSubReg(DstMO.getSubReg());
7362 LoadDst.setIsUndef();
7363 return &LoadMI;
7364 }
7365 }
7366 }
7367
7368 // Cannot fold.
7369 return nullptr;
7370}
7371
7373 StackOffset &SOffset,
7374 bool *OutUseUnscaledOp,
7375 unsigned *OutUnscaledOp,
7376 int64_t *EmittableOffset) {
7377 // Set output values in case of early exit.
7378 if (EmittableOffset)
7379 *EmittableOffset = 0;
7380 if (OutUseUnscaledOp)
7381 *OutUseUnscaledOp = false;
7382 if (OutUnscaledOp)
7383 *OutUnscaledOp = 0;
7384
7385 // Exit early for structured vector spills/fills as they can't take an
7386 // immediate offset.
7387 switch (MI.getOpcode()) {
7388 default:
7389 break;
7390 case AArch64::LD1Rv1d:
7391 case AArch64::LD1Rv2s:
7392 case AArch64::LD1Rv2d:
7393 case AArch64::LD1Rv4h:
7394 case AArch64::LD1Rv4s:
7395 case AArch64::LD1Rv8b:
7396 case AArch64::LD1Rv8h:
7397 case AArch64::LD1Rv16b:
7398 case AArch64::LD1Twov2d:
7399 case AArch64::LD1Threev2d:
7400 case AArch64::LD1Fourv2d:
7401 case AArch64::LD1Twov1d:
7402 case AArch64::LD1Threev1d:
7403 case AArch64::LD1Fourv1d:
7404 case AArch64::ST1Twov2d:
7405 case AArch64::ST1Threev2d:
7406 case AArch64::ST1Fourv2d:
7407 case AArch64::ST1Twov1d:
7408 case AArch64::ST1Threev1d:
7409 case AArch64::ST1Fourv1d:
7410 case AArch64::ST1i8:
7411 case AArch64::ST1i16:
7412 case AArch64::ST1i32:
7413 case AArch64::ST1i64:
7414 case AArch64::IRG:
7415 case AArch64::IRGstack:
7416 case AArch64::STGloop:
7417 case AArch64::STZGloop:
7419 }
7420
7421 // Get the min/max offset and the scale.
7422 TypeSize ScaleValue(0U, false), Width(0U, false);
7423 int64_t MinOff, MaxOff;
7424 if (!AArch64InstrInfo::getMemOpInfo(MI.getOpcode(), ScaleValue, Width, MinOff,
7425 MaxOff))
7426 llvm_unreachable("unhandled opcode in isAArch64FrameOffsetLegal");
7427
7428 // Construct the complete offset.
7429 bool IsMulVL = ScaleValue.isScalable();
7430 unsigned Scale = ScaleValue.getKnownMinValue();
7431 int64_t Offset = IsMulVL ? SOffset.getScalable() : SOffset.getFixed();
7432
7433 const MachineOperand &ImmOpnd =
7434 MI.getOperand(AArch64InstrInfo::getLoadStoreImmIdx(MI.getOpcode()));
7435 Offset += ImmOpnd.getImm() * Scale;
7436
7437 // If the offset doesn't match the scale, we rewrite the instruction to
7438 // use the unscaled instruction instead. Likewise, if we have a negative
7439 // offset and there is an unscaled op to use.
7440 std::optional<unsigned> UnscaledOp =
7442 bool useUnscaledOp = UnscaledOp && (Offset % Scale || Offset < 0);
7443 if (useUnscaledOp &&
7444 !AArch64InstrInfo::getMemOpInfo(*UnscaledOp, ScaleValue, Width, MinOff,
7445 MaxOff))
7446 llvm_unreachable("unhandled opcode in isAArch64FrameOffsetLegal");
7447
7448 Scale = ScaleValue.getKnownMinValue();
7449 assert(IsMulVL == ScaleValue.isScalable() &&
7450 "Unscaled opcode has different value for scalable");
7451
7452 int64_t Remainder = Offset % Scale;
7453 assert(!(Remainder && useUnscaledOp) &&
7454 "Cannot have remainder when using unscaled op");
7455
7456 assert(MinOff < MaxOff && "Unexpected Min/Max offsets");
7457 int64_t NewOffset = Offset / Scale;
7458 if (MinOff <= NewOffset && NewOffset <= MaxOff)
7459 Offset = Remainder;
7460 else {
7461 // Try to minimise the number of instructions required to materialise the
7462 // offset calculation. Specifically, for fixed offsets, if masking out the
7463 // low 12 bits leaves a legal add immediate, we can realise the offset
7464 // calculation with a single add instruction. Whenever this is possible,
7465 // prefer this split.
7466 int64_t HighPart = Offset & ~0xFFF;
7467 int64_t LowPart = Offset & 0xFFF;
7468 int64_t LowScaled = LowPart / Scale;
7469 if (!IsMulVL && NewOffset >= 0 && LowPart % Scale == 0 &&
7470 MinOff <= LowScaled && LowScaled <= MaxOff &&
7472 NewOffset = LowScaled;
7473 Offset = HighPart;
7474 } else {
7475 // Default to a greedy split: take the memop immediate to be maximum /
7476 // minimum expressible offset and materialise the remainder.
7477 NewOffset = NewOffset < 0 ? MinOff : MaxOff;
7478 Offset = Offset - (NewOffset * Scale);
7479 }
7480 }
7481
7482 if (EmittableOffset)
7483 *EmittableOffset = NewOffset;
7484 if (OutUseUnscaledOp)
7485 *OutUseUnscaledOp = useUnscaledOp;
7486 if (OutUnscaledOp && UnscaledOp)
7487 *OutUnscaledOp = *UnscaledOp;
7488
7489 if (IsMulVL)
7490 SOffset = StackOffset::get(SOffset.getFixed(), Offset);
7491 else
7492 SOffset = StackOffset::get(Offset, SOffset.getScalable());
7494 (SOffset ? 0 : AArch64FrameOffsetIsLegal);
7495}
7496
7498 unsigned FrameReg, StackOffset &Offset,
7499 const AArch64InstrInfo *TII) {
7500 unsigned Opcode = MI.getOpcode();
7501 unsigned ImmIdx = FrameRegIdx + 1;
7502
7503 if (Opcode == AArch64::ADDSXri || Opcode == AArch64::ADDXri) {
7504 Offset += StackOffset::getFixed(MI.getOperand(ImmIdx).getImm());
7505 emitFrameOffset(*MI.getParent(), MI, MI.getDebugLoc(),
7506 MI.getOperand(0).getReg(), FrameReg, Offset, TII,
7507 MachineInstr::NoFlags, (Opcode == AArch64::ADDSXri));
7508 MI.eraseFromParent();
7509 Offset = StackOffset();
7510 return true;
7511 }
7512
7513 int64_t NewOffset;
7514 unsigned UnscaledOp;
7515 bool UseUnscaledOp;
7516 int Status = isAArch64FrameOffsetLegal(MI, Offset, &UseUnscaledOp,
7517 &UnscaledOp, &NewOffset);
7520 // Replace the FrameIndex with FrameReg.
7521 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
7522 if (UseUnscaledOp)
7523 MI.setDesc(TII->get(UnscaledOp));
7524
7525 MI.getOperand(ImmIdx).ChangeToImmediate(NewOffset);
7526 return !Offset;
7527 }
7528
7529 return false;
7530}
7531
7537
7538MCInst AArch64InstrInfo::getNop() const { return MCInstBuilder(AArch64::NOP); }
7539
7540// AArch64 supports MachineCombiner.
7541bool AArch64InstrInfo::useMachineCombiner() const { return true; }
7542
7543// True when Opc sets flag
7544static bool isCombineInstrSettingFlag(unsigned Opc) {
7545 switch (Opc) {
7546 case AArch64::ADDSWrr:
7547 case AArch64::ADDSWri:
7548 case AArch64::ADDSXrr:
7549 case AArch64::ADDSXri:
7550 case AArch64::SUBSWrr:
7551 case AArch64::SUBSXrr:
7552 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7553 case AArch64::SUBSWri:
7554 case AArch64::SUBSXri:
7555 return true;
7556 default:
7557 break;
7558 }
7559 return false;
7560}
7561
7562// 32b Opcodes that can be combined with a MUL
7563static bool isCombineInstrCandidate32(unsigned Opc) {
7564 switch (Opc) {
7565 case AArch64::ADDWrr:
7566 case AArch64::ADDWri:
7567 case AArch64::SUBWrr:
7568 case AArch64::ADDSWrr:
7569 case AArch64::ADDSWri:
7570 case AArch64::SUBSWrr:
7571 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7572 case AArch64::SUBWri:
7573 case AArch64::SUBSWri:
7574 return true;
7575 default:
7576 break;
7577 }
7578 return false;
7579}
7580
7581// 64b Opcodes that can be combined with a MUL
7582static bool isCombineInstrCandidate64(unsigned Opc) {
7583 switch (Opc) {
7584 case AArch64::ADDXrr:
7585 case AArch64::ADDXri:
7586 case AArch64::SUBXrr:
7587 case AArch64::ADDSXrr:
7588 case AArch64::ADDSXri:
7589 case AArch64::SUBSXrr:
7590 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7591 case AArch64::SUBXri:
7592 case AArch64::SUBSXri:
7593 case AArch64::ADDv8i8:
7594 case AArch64::ADDv16i8:
7595 case AArch64::ADDv4i16:
7596 case AArch64::ADDv8i16:
7597 case AArch64::ADDv2i32:
7598 case AArch64::ADDv4i32:
7599 case AArch64::SUBv8i8:
7600 case AArch64::SUBv16i8:
7601 case AArch64::SUBv4i16:
7602 case AArch64::SUBv8i16:
7603 case AArch64::SUBv2i32:
7604 case AArch64::SUBv4i32:
7605 return true;
7606 default:
7607 break;
7608 }
7609 return false;
7610}
7611
7612// FP Opcodes that can be combined with a FMUL.
7613static bool isCombineInstrCandidateFP(const MachineInstr &Inst) {
7614 switch (Inst.getOpcode()) {
7615 default:
7616 break;
7617 case AArch64::FADDHrr:
7618 case AArch64::FADDSrr:
7619 case AArch64::FADDDrr:
7620 case AArch64::FADDv4f16:
7621 case AArch64::FADDv8f16:
7622 case AArch64::FADDv2f32:
7623 case AArch64::FADDv2f64:
7624 case AArch64::FADDv4f32:
7625 case AArch64::FSUBHrr:
7626 case AArch64::FSUBSrr:
7627 case AArch64::FSUBDrr:
7628 case AArch64::FSUBv4f16:
7629 case AArch64::FSUBv8f16:
7630 case AArch64::FSUBv2f32:
7631 case AArch64::FSUBv2f64:
7632 case AArch64::FSUBv4f32:
7633 // We can fuse FADD/FSUB with FMUL, if FADD/FSUB has the contract fast-math
7634 // flag.
7635 return Inst.getFlag(MachineInstr::FmContract);
7636 }
7637 return false;
7638}
7639
7640// Opcodes that can be combined with a MUL
7644
7645//
7646// Utility routine that checks if \param MO is defined by an
7647// \param CombineOpc instruction in the basic block \param MBB
7649 unsigned CombineOpc, unsigned ZeroReg = 0,
7650 bool CheckZeroReg = false) {
7651 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
7652 MachineInstr *MI = nullptr;
7653
7654 if (MO.isReg() && MO.getReg().isVirtual())
7655 MI = MRI.getUniqueVRegDef(MO.getReg());
7656 // And it needs to be in the trace (otherwise, it won't have a depth).
7657 if (!MI || MI->getParent() != &MBB || MI->getOpcode() != CombineOpc)
7658 return false;
7659 // Must only used by the user we combine with.
7660 if (!MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()))
7661 return false;
7662
7663 if (CheckZeroReg) {
7664 assert(MI->getNumOperands() >= 4 && MI->getOperand(0).isReg() &&
7665 MI->getOperand(1).isReg() && MI->getOperand(2).isReg() &&
7666 MI->getOperand(3).isReg() && "MAdd/MSub must have a least 4 regs");
7667 // The third input reg must be zero.
7668 if (MI->getOperand(3).getReg() != ZeroReg)
7669 return false;
7670 }
7671
7672 if (isCombineInstrSettingFlag(CombineOpc) &&
7673 MI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) == -1)
7674 return false;
7675
7676 return true;
7677}
7678
7679//
7680// Is \param MO defined by an integer multiply and can be combined?
7682 unsigned MulOpc, unsigned ZeroReg) {
7683 return canCombine(MBB, MO, MulOpc, ZeroReg, true);
7684}
7685
7686//
7687// Is \param MO defined by a floating-point multiply and can be combined?
7689 unsigned MulOpc) {
7690 return canCombine(MBB, MO, MulOpc);
7691}
7692
7693// TODO: There are many more machine instruction opcodes to match:
7694// 1. Other data types (integer, vectors)
7695// 2. Other math / logic operations (xor, or)
7696// 3. Other forms of the same operation (intrinsics and other variants)
7697bool AArch64InstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst,
7698 bool Invert) const {
7699 if (Invert)
7700 return false;
7701 switch (Inst.getOpcode()) {
7702 // == Floating-point types ==
7703 // -- Floating-point instructions --
7704 case AArch64::FADDHrr:
7705 case AArch64::FADDSrr:
7706 case AArch64::FADDDrr:
7707 case AArch64::FMULHrr:
7708 case AArch64::FMULSrr:
7709 case AArch64::FMULDrr:
7710 case AArch64::FMULX16:
7711 case AArch64::FMULX32:
7712 case AArch64::FMULX64:
7713 // -- Advanced SIMD instructions --
7714 case AArch64::FADDv4f16:
7715 case AArch64::FADDv8f16:
7716 case AArch64::FADDv2f32:
7717 case AArch64::FADDv4f32:
7718 case AArch64::FADDv2f64:
7719 case AArch64::FMULv4f16:
7720 case AArch64::FMULv8f16:
7721 case AArch64::FMULv2f32:
7722 case AArch64::FMULv4f32:
7723 case AArch64::FMULv2f64:
7724 case AArch64::FMULXv4f16:
7725 case AArch64::FMULXv8f16:
7726 case AArch64::FMULXv2f32:
7727 case AArch64::FMULXv4f32:
7728 case AArch64::FMULXv2f64:
7729 // -- SVE instructions --
7730 // Opcodes FMULX_ZZZ_? don't exist because there is no unpredicated FMULX
7731 // in the SVE instruction set (though there are predicated ones).
7732 case AArch64::FADD_ZZZ_H:
7733 case AArch64::FADD_ZZZ_S:
7734 case AArch64::FADD_ZZZ_D:
7735 case AArch64::FMUL_ZZZ_H:
7736 case AArch64::FMUL_ZZZ_S:
7737 case AArch64::FMUL_ZZZ_D:
7740
7741 // == Integer types ==
7742 // -- Base instructions --
7743 // Opcodes MULWrr and MULXrr don't exist because
7744 // `MUL <Wd>, <Wn>, <Wm>` and `MUL <Xd>, <Xn>, <Xm>` are aliases of
7745 // `MADD <Wd>, <Wn>, <Wm>, WZR` and `MADD <Xd>, <Xn>, <Xm>, XZR` respectively.
7746 // The machine-combiner does not support three-source-operands machine
7747 // instruction. So we cannot reassociate MULs.
7748 case AArch64::ADDWrr:
7749 case AArch64::ADDXrr:
7750 case AArch64::ANDWrr:
7751 case AArch64::ANDXrr:
7752 case AArch64::ORRWrr:
7753 case AArch64::ORRXrr:
7754 case AArch64::EORWrr:
7755 case AArch64::EORXrr:
7756 case AArch64::EONWrr:
7757 case AArch64::EONXrr:
7758 // -- Advanced SIMD instructions --
7759 // Opcodes MULv1i64 and MULv2i64 don't exist because there is no 64-bit MUL
7760 // in the Advanced SIMD instruction set.
7761 case AArch64::ADDv8i8:
7762 case AArch64::ADDv16i8:
7763 case AArch64::ADDv4i16:
7764 case AArch64::ADDv8i16:
7765 case AArch64::ADDv2i32:
7766 case AArch64::ADDv4i32:
7767 case AArch64::ADDv1i64:
7768 case AArch64::ADDv2i64:
7769 case AArch64::MULv8i8:
7770 case AArch64::MULv16i8:
7771 case AArch64::MULv4i16:
7772 case AArch64::MULv8i16:
7773 case AArch64::MULv2i32:
7774 case AArch64::MULv4i32:
7775 case AArch64::ANDv8i8:
7776 case AArch64::ANDv16i8:
7777 case AArch64::ORRv8i8:
7778 case AArch64::ORRv16i8:
7779 case AArch64::EORv8i8:
7780 case AArch64::EORv16i8:
7781 // -- SVE instructions --
7782 case AArch64::ADD_ZZZ_B:
7783 case AArch64::ADD_ZZZ_H:
7784 case AArch64::ADD_ZZZ_S:
7785 case AArch64::ADD_ZZZ_D:
7786 case AArch64::MUL_ZZZ_B:
7787 case AArch64::MUL_ZZZ_H:
7788 case AArch64::MUL_ZZZ_S:
7789 case AArch64::MUL_ZZZ_D:
7790 case AArch64::AND_ZZZ:
7791 case AArch64::ORR_ZZZ:
7792 case AArch64::EOR_ZZZ:
7793 return true;
7794
7795 default:
7796 return false;
7797 }
7798}
7799
7800/// Find instructions that can be turned into madd.
7802 SmallVectorImpl<unsigned> &Patterns) {
7803 unsigned Opc = Root.getOpcode();
7804 MachineBasicBlock &MBB = *Root.getParent();
7805 bool Found = false;
7806
7808 return false;
7810 int Cmp_NZCV =
7811 Root.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true);
7812 // When NZCV is live bail out.
7813 if (Cmp_NZCV == -1)
7814 return false;
7815 unsigned NewOpc = convertToNonFlagSettingOpc(Root);
7816 // When opcode can't change bail out.
7817 // CHECKME: do we miss any cases for opcode conversion?
7818 if (NewOpc == Opc)
7819 return false;
7820 Opc = NewOpc;
7821 }
7822
7823 auto setFound = [&](int Opcode, int Operand, unsigned ZeroReg,
7824 unsigned Pattern) {
7825 if (canCombineWithMUL(MBB, Root.getOperand(Operand), Opcode, ZeroReg)) {
7826 Patterns.push_back(Pattern);
7827 Found = true;
7828 }
7829 };
7830
7831 auto setVFound = [&](int Opcode, int Operand, unsigned Pattern) {
7832 if (canCombine(MBB, Root.getOperand(Operand), Opcode)) {
7833 Patterns.push_back(Pattern);
7834 Found = true;
7835 }
7836 };
7837
7839
7840 switch (Opc) {
7841 default:
7842 break;
7843 case AArch64::ADDWrr:
7844 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
7845 "ADDWrr does not have register operands");
7846 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDW_OP1);
7847 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULADDW_OP2);
7848 break;
7849 case AArch64::ADDXrr:
7850 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDX_OP1);
7851 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULADDX_OP2);
7852 break;
7853 case AArch64::SUBWrr:
7854 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULSUBW_OP2);
7855 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBW_OP1);
7856 break;
7857 case AArch64::SUBXrr:
7858 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULSUBX_OP2);
7859 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBX_OP1);
7860 break;
7861 case AArch64::ADDWri:
7862 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDWI_OP1);
7863 break;
7864 case AArch64::ADDXri:
7865 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDXI_OP1);
7866 break;
7867 case AArch64::SUBWri:
7868 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBWI_OP1);
7869 break;
7870 case AArch64::SUBXri:
7871 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBXI_OP1);
7872 break;
7873 case AArch64::ADDv8i8:
7874 setVFound(AArch64::MULv8i8, 1, MCP::MULADDv8i8_OP1);
7875 setVFound(AArch64::MULv8i8, 2, MCP::MULADDv8i8_OP2);
7876 break;
7877 case AArch64::ADDv16i8:
7878 setVFound(AArch64::MULv16i8, 1, MCP::MULADDv16i8_OP1);
7879 setVFound(AArch64::MULv16i8, 2, MCP::MULADDv16i8_OP2);
7880 break;
7881 case AArch64::ADDv4i16:
7882 setVFound(AArch64::MULv4i16, 1, MCP::MULADDv4i16_OP1);
7883 setVFound(AArch64::MULv4i16, 2, MCP::MULADDv4i16_OP2);
7884 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULADDv4i16_indexed_OP1);
7885 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULADDv4i16_indexed_OP2);
7886 break;
7887 case AArch64::ADDv8i16:
7888 setVFound(AArch64::MULv8i16, 1, MCP::MULADDv8i16_OP1);
7889 setVFound(AArch64::MULv8i16, 2, MCP::MULADDv8i16_OP2);
7890 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULADDv8i16_indexed_OP1);
7891 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULADDv8i16_indexed_OP2);
7892 break;
7893 case AArch64::ADDv2i32:
7894 setVFound(AArch64::MULv2i32, 1, MCP::MULADDv2i32_OP1);
7895 setVFound(AArch64::MULv2i32, 2, MCP::MULADDv2i32_OP2);
7896 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULADDv2i32_indexed_OP1);
7897 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULADDv2i32_indexed_OP2);
7898 break;
7899 case AArch64::ADDv4i32:
7900 setVFound(AArch64::MULv4i32, 1, MCP::MULADDv4i32_OP1);
7901 setVFound(AArch64::MULv4i32, 2, MCP::MULADDv4i32_OP2);
7902 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULADDv4i32_indexed_OP1);
7903 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULADDv4i32_indexed_OP2);
7904 break;
7905 case AArch64::SUBv8i8:
7906 setVFound(AArch64::MULv8i8, 1, MCP::MULSUBv8i8_OP1);
7907 setVFound(AArch64::MULv8i8, 2, MCP::MULSUBv8i8_OP2);
7908 break;
7909 case AArch64::SUBv16i8:
7910 setVFound(AArch64::MULv16i8, 1, MCP::MULSUBv16i8_OP1);
7911 setVFound(AArch64::MULv16i8, 2, MCP::MULSUBv16i8_OP2);
7912 break;
7913 case AArch64::SUBv4i16:
7914 setVFound(AArch64::MULv4i16, 1, MCP::MULSUBv4i16_OP1);
7915 setVFound(AArch64::MULv4i16, 2, MCP::MULSUBv4i16_OP2);
7916 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULSUBv4i16_indexed_OP1);
7917 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULSUBv4i16_indexed_OP2);
7918 break;
7919 case AArch64::SUBv8i16:
7920 setVFound(AArch64::MULv8i16, 1, MCP::MULSUBv8i16_OP1);
7921 setVFound(AArch64::MULv8i16, 2, MCP::MULSUBv8i16_OP2);
7922 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULSUBv8i16_indexed_OP1);
7923 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULSUBv8i16_indexed_OP2);
7924 break;
7925 case AArch64::SUBv2i32:
7926 setVFound(AArch64::MULv2i32, 1, MCP::MULSUBv2i32_OP1);
7927 setVFound(AArch64::MULv2i32, 2, MCP::MULSUBv2i32_OP2);
7928 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULSUBv2i32_indexed_OP1);
7929 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULSUBv2i32_indexed_OP2);
7930 break;
7931 case AArch64::SUBv4i32:
7932 setVFound(AArch64::MULv4i32, 1, MCP::MULSUBv4i32_OP1);
7933 setVFound(AArch64::MULv4i32, 2, MCP::MULSUBv4i32_OP2);
7934 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULSUBv4i32_indexed_OP1);
7935 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULSUBv4i32_indexed_OP2);
7936 break;
7937 }
7938 return Found;
7939}
7940
7941bool AArch64InstrInfo::isAccumulationOpcode(unsigned Opcode) const {
7942 switch (Opcode) {
7943 default:
7944 break;
7945 case AArch64::UABALB_ZZZ_D:
7946 case AArch64::UABALB_ZZZ_H:
7947 case AArch64::UABALB_ZZZ_S:
7948 case AArch64::UABALT_ZZZ_D:
7949 case AArch64::UABALT_ZZZ_H:
7950 case AArch64::UABALT_ZZZ_S:
7951 case AArch64::SABALB_ZZZ_D:
7952 case AArch64::SABALB_ZZZ_S:
7953 case AArch64::SABALB_ZZZ_H:
7954 case AArch64::SABALT_ZZZ_D:
7955 case AArch64::SABALT_ZZZ_S:
7956 case AArch64::SABALT_ZZZ_H:
7957 case AArch64::UABALv16i8_v8i16:
7958 case AArch64::UABALv2i32_v2i64:
7959 case AArch64::UABALv4i16_v4i32:
7960 case AArch64::UABALv4i32_v2i64:
7961 case AArch64::UABALv8i16_v4i32:
7962 case AArch64::UABALv8i8_v8i16:
7963 case AArch64::UABAv16i8:
7964 case AArch64::UABAv2i32:
7965 case AArch64::UABAv4i16:
7966 case AArch64::UABAv4i32:
7967 case AArch64::UABAv8i16:
7968 case AArch64::UABAv8i8:
7969 case AArch64::SABALv16i8_v8i16:
7970 case AArch64::SABALv2i32_v2i64:
7971 case AArch64::SABALv4i16_v4i32:
7972 case AArch64::SABALv4i32_v2i64:
7973 case AArch64::SABALv8i16_v4i32:
7974 case AArch64::SABALv8i8_v8i16:
7975 case AArch64::SABAv16i8:
7976 case AArch64::SABAv2i32:
7977 case AArch64::SABAv4i16:
7978 case AArch64::SABAv4i32:
7979 case AArch64::SABAv8i16:
7980 case AArch64::SABAv8i8:
7981 return true;
7982 }
7983
7984 return false;
7985}
7986
7987unsigned AArch64InstrInfo::getAccumulationStartOpcode(
7988 unsigned AccumulationOpcode) const {
7989 switch (AccumulationOpcode) {
7990 default:
7991 llvm_unreachable("Unsupported accumulation Opcode!");
7992 case AArch64::UABALB_ZZZ_D:
7993 return AArch64::UABDLB_ZZZ_D;
7994 case AArch64::UABALB_ZZZ_H:
7995 return AArch64::UABDLB_ZZZ_H;
7996 case AArch64::UABALB_ZZZ_S:
7997 return AArch64::UABDLB_ZZZ_S;
7998 case AArch64::UABALT_ZZZ_D:
7999 return AArch64::UABDLT_ZZZ_D;
8000 case AArch64::UABALT_ZZZ_H:
8001 return AArch64::UABDLT_ZZZ_H;
8002 case AArch64::UABALT_ZZZ_S:
8003 return AArch64::UABDLT_ZZZ_S;
8004 case AArch64::UABALv16i8_v8i16:
8005 return AArch64::UABDLv16i8_v8i16;
8006 case AArch64::UABALv2i32_v2i64:
8007 return AArch64::UABDLv2i32_v2i64;
8008 case AArch64::UABALv4i16_v4i32:
8009 return AArch64::UABDLv4i16_v4i32;
8010 case AArch64::UABALv4i32_v2i64:
8011 return AArch64::UABDLv4i32_v2i64;
8012 case AArch64::UABALv8i16_v4i32:
8013 return AArch64::UABDLv8i16_v4i32;
8014 case AArch64::UABALv8i8_v8i16:
8015 return AArch64::UABDLv8i8_v8i16;
8016 case AArch64::UABAv16i8:
8017 return AArch64::UABDv16i8;
8018 case AArch64::UABAv2i32:
8019 return AArch64::UABDv2i32;
8020 case AArch64::UABAv4i16:
8021 return AArch64::UABDv4i16;
8022 case AArch64::UABAv4i32:
8023 return AArch64::UABDv4i32;
8024 case AArch64::UABAv8i16:
8025 return AArch64::UABDv8i16;
8026 case AArch64::UABAv8i8:
8027 return AArch64::UABDv8i8;
8028 case AArch64::SABALB_ZZZ_D:
8029 return AArch64::SABDLB_ZZZ_D;
8030 case AArch64::SABALB_ZZZ_S:
8031 return AArch64::SABDLB_ZZZ_S;
8032 case AArch64::SABALB_ZZZ_H:
8033 return AArch64::SABDLB_ZZZ_H;
8034 case AArch64::SABALT_ZZZ_D:
8035 return AArch64::SABDLT_ZZZ_D;
8036 case AArch64::SABALT_ZZZ_S:
8037 return AArch64::SABDLT_ZZZ_S;
8038 case AArch64::SABALT_ZZZ_H:
8039 return AArch64::SABDLT_ZZZ_H;
8040 case AArch64::SABALv16i8_v8i16:
8041 return AArch64::SABDLv16i8_v8i16;
8042 case AArch64::SABALv2i32_v2i64:
8043 return AArch64::SABDLv2i32_v2i64;
8044 case AArch64::SABALv4i16_v4i32:
8045 return AArch64::SABDLv4i16_v4i32;
8046 case AArch64::SABALv4i32_v2i64:
8047 return AArch64::SABDLv4i32_v2i64;
8048 case AArch64::SABALv8i16_v4i32:
8049 return AArch64::SABDLv8i16_v4i32;
8050 case AArch64::SABALv8i8_v8i16:
8051 return AArch64::SABDLv8i8_v8i16;
8052 case AArch64::SABAv16i8:
8053 return AArch64::SABDv16i8;
8054 case AArch64::SABAv2i32:
8055 return AArch64::SABDv2i32;
8056 case AArch64::SABAv4i16:
8057 return AArch64::SABDv4i16;
8058 case AArch64::SABAv4i32:
8059 return AArch64::SABDv4i32;
8060 case AArch64::SABAv8i16:
8061 return AArch64::SABDv8i16;
8062 case AArch64::SABAv8i8:
8063 return AArch64::SABDv8i8;
8064 }
8065}
8066
8067/// Floating-Point Support
8068
8069/// Find instructions that can be turned into madd.
8071 SmallVectorImpl<unsigned> &Patterns) {
8072
8073 if (!isCombineInstrCandidateFP(Root))
8074 return false;
8075
8076 MachineBasicBlock &MBB = *Root.getParent();
8077 bool Found = false;
8078
8079 auto Match = [&](int Opcode, int Operand, unsigned Pattern) -> bool {
8080 if (canCombineWithFMUL(MBB, Root.getOperand(Operand), Opcode)) {
8081 Patterns.push_back(Pattern);
8082 return true;
8083 }
8084 return false;
8085 };
8086
8088
8089 switch (Root.getOpcode()) {
8090 default:
8091 assert(false && "Unsupported FP instruction in combiner\n");
8092 break;
8093 case AArch64::FADDHrr:
8094 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
8095 "FADDHrr does not have register operands");
8096
8097 Found = Match(AArch64::FMULHrr, 1, MCP::FMULADDH_OP1);
8098 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULADDH_OP2);
8099 break;
8100 case AArch64::FADDSrr:
8101 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
8102 "FADDSrr does not have register operands");
8103
8104 Found |= Match(AArch64::FMULSrr, 1, MCP::FMULADDS_OP1) ||
8105 Match(AArch64::FMULv1i32_indexed, 1, MCP::FMLAv1i32_indexed_OP1);
8106
8107 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULADDS_OP2) ||
8108 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLAv1i32_indexed_OP2);
8109 break;
8110 case AArch64::FADDDrr:
8111 Found |= Match(AArch64::FMULDrr, 1, MCP::FMULADDD_OP1) ||
8112 Match(AArch64::FMULv1i64_indexed, 1, MCP::FMLAv1i64_indexed_OP1);
8113
8114 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULADDD_OP2) ||
8115 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLAv1i64_indexed_OP2);
8116 break;
8117 case AArch64::FADDv4f16:
8118 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLAv4i16_indexed_OP1) ||
8119 Match(AArch64::FMULv4f16, 1, MCP::FMLAv4f16_OP1);
8120
8121 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLAv4i16_indexed_OP2) ||
8122 Match(AArch64::FMULv4f16, 2, MCP::FMLAv4f16_OP2);
8123 break;
8124 case AArch64::FADDv8f16:
8125 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLAv8i16_indexed_OP1) ||
8126 Match(AArch64::FMULv8f16, 1, MCP::FMLAv8f16_OP1);
8127
8128 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLAv8i16_indexed_OP2) ||
8129 Match(AArch64::FMULv8f16, 2, MCP::FMLAv8f16_OP2);
8130 break;
8131 case AArch64::FADDv2f32:
8132 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLAv2i32_indexed_OP1) ||
8133 Match(AArch64::FMULv2f32, 1, MCP::FMLAv2f32_OP1);
8134
8135 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLAv2i32_indexed_OP2) ||
8136 Match(AArch64::FMULv2f32, 2, MCP::FMLAv2f32_OP2);
8137 break;
8138 case AArch64::FADDv2f64:
8139 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLAv2i64_indexed_OP1) ||
8140 Match(AArch64::FMULv2f64, 1, MCP::FMLAv2f64_OP1);
8141
8142 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLAv2i64_indexed_OP2) ||
8143 Match(AArch64::FMULv2f64, 2, MCP::FMLAv2f64_OP2);
8144 break;
8145 case AArch64::FADDv4f32:
8146 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLAv4i32_indexed_OP1) ||
8147 Match(AArch64::FMULv4f32, 1, MCP::FMLAv4f32_OP1);
8148
8149 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLAv4i32_indexed_OP2) ||
8150 Match(AArch64::FMULv4f32, 2, MCP::FMLAv4f32_OP2);
8151 break;
8152 case AArch64::FSUBHrr:
8153 Found = Match(AArch64::FMULHrr, 1, MCP::FMULSUBH_OP1);
8154 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULSUBH_OP2);
8155 Found |= Match(AArch64::FNMULHrr, 1, MCP::FNMULSUBH_OP1);
8156 break;
8157 case AArch64::FSUBSrr:
8158 Found = Match(AArch64::FMULSrr, 1, MCP::FMULSUBS_OP1);
8159
8160 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULSUBS_OP2) ||
8161 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLSv1i32_indexed_OP2);
8162
8163 Found |= Match(AArch64::FNMULSrr, 1, MCP::FNMULSUBS_OP1);
8164 break;
8165 case AArch64::FSUBDrr:
8166 Found = Match(AArch64::FMULDrr, 1, MCP::FMULSUBD_OP1);
8167
8168 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULSUBD_OP2) ||
8169 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLSv1i64_indexed_OP2);
8170
8171 Found |= Match(AArch64::FNMULDrr, 1, MCP::FNMULSUBD_OP1);
8172 break;
8173 case AArch64::FSUBv4f16:
8174 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLSv4i16_indexed_OP2) ||
8175 Match(AArch64::FMULv4f16, 2, MCP::FMLSv4f16_OP2);
8176
8177 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLSv4i16_indexed_OP1) ||
8178 Match(AArch64::FMULv4f16, 1, MCP::FMLSv4f16_OP1);
8179 break;
8180 case AArch64::FSUBv8f16:
8181 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLSv8i16_indexed_OP2) ||
8182 Match(AArch64::FMULv8f16, 2, MCP::FMLSv8f16_OP2);
8183
8184 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLSv8i16_indexed_OP1) ||
8185 Match(AArch64::FMULv8f16, 1, MCP::FMLSv8f16_OP1);
8186 break;
8187 case AArch64::FSUBv2f32:
8188 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLSv2i32_indexed_OP2) ||
8189 Match(AArch64::FMULv2f32, 2, MCP::FMLSv2f32_OP2);
8190
8191 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLSv2i32_indexed_OP1) ||
8192 Match(AArch64::FMULv2f32, 1, MCP::FMLSv2f32_OP1);
8193 break;
8194 case AArch64::FSUBv2f64:
8195 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLSv2i64_indexed_OP2) ||
8196 Match(AArch64::FMULv2f64, 2, MCP::FMLSv2f64_OP2);
8197
8198 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLSv2i64_indexed_OP1) ||
8199 Match(AArch64::FMULv2f64, 1, MCP::FMLSv2f64_OP1);
8200 break;
8201 case AArch64::FSUBv4f32:
8202 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLSv4i32_indexed_OP2) ||
8203 Match(AArch64::FMULv4f32, 2, MCP::FMLSv4f32_OP2);
8204
8205 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLSv4i32_indexed_OP1) ||
8206 Match(AArch64::FMULv4f32, 1, MCP::FMLSv4f32_OP1);
8207 break;
8208 }
8209 return Found;
8210}
8211
8213 SmallVectorImpl<unsigned> &Patterns) {
8214 MachineBasicBlock &MBB = *Root.getParent();
8215 bool Found = false;
8216
8217 auto Match = [&](unsigned Opcode, int Operand, unsigned Pattern) -> bool {
8218 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8219 MachineOperand &MO = Root.getOperand(Operand);
8220 MachineInstr *MI = nullptr;
8221 if (MO.isReg() && MO.getReg().isVirtual())
8222 MI = MRI.getUniqueVRegDef(MO.getReg());
8223 // Ignore No-op COPYs in FMUL(COPY(DUP(..)))
8224 if (MI && MI->getOpcode() == TargetOpcode::COPY &&
8225 MI->getOperand(1).getReg().isVirtual())
8226 MI = MRI.getUniqueVRegDef(MI->getOperand(1).getReg());
8227 if (MI && MI->getOpcode() == Opcode) {
8228 Patterns.push_back(Pattern);
8229 return true;
8230 }
8231 return false;
8232 };
8233
8235
8236 switch (Root.getOpcode()) {
8237 default:
8238 return false;
8239 case AArch64::FMULv2f32:
8240 Found = Match(AArch64::DUPv2i32lane, 1, MCP::FMULv2i32_indexed_OP1);
8241 Found |= Match(AArch64::DUPv2i32lane, 2, MCP::FMULv2i32_indexed_OP2);
8242 break;
8243 case AArch64::FMULv2f64:
8244 Found = Match(AArch64::DUPv2i64lane, 1, MCP::FMULv2i64_indexed_OP1);
8245 Found |= Match(AArch64::DUPv2i64lane, 2, MCP::FMULv2i64_indexed_OP2);
8246 break;
8247 case AArch64::FMULv4f16:
8248 Found = Match(AArch64::DUPv4i16lane, 1, MCP::FMULv4i16_indexed_OP1);
8249 Found |= Match(AArch64::DUPv4i16lane, 2, MCP::FMULv4i16_indexed_OP2);
8250 break;
8251 case AArch64::FMULv4f32:
8252 Found = Match(AArch64::DUPv4i32lane, 1, MCP::FMULv4i32_indexed_OP1);
8253 Found |= Match(AArch64::DUPv4i32lane, 2, MCP::FMULv4i32_indexed_OP2);
8254 break;
8255 case AArch64::FMULv8f16:
8256 Found = Match(AArch64::DUPv8i16lane, 1, MCP::FMULv8i16_indexed_OP1);
8257 Found |= Match(AArch64::DUPv8i16lane, 2, MCP::FMULv8i16_indexed_OP2);
8258 break;
8259 }
8260
8261 return Found;
8262}
8263
8265 SmallVectorImpl<unsigned> &Patterns) {
8266 unsigned Opc = Root.getOpcode();
8267 MachineBasicBlock &MBB = *Root.getParent();
8268 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8269
8270 auto Match = [&](unsigned Opcode, unsigned Pattern) -> bool {
8271 MachineOperand &MO = Root.getOperand(1);
8273 if (MI != nullptr && (MI->getOpcode() == Opcode) &&
8274 MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()) &&
8278 MI->getFlag(MachineInstr::MIFlag::FmNsz)) {
8279 Patterns.push_back(Pattern);
8280 return true;
8281 }
8282 return false;
8283 };
8284
8285 switch (Opc) {
8286 default:
8287 break;
8288 case AArch64::FNEGDr:
8289 return Match(AArch64::FMADDDrrr, AArch64MachineCombinerPattern::FNMADD);
8290 case AArch64::FNEGSr:
8291 return Match(AArch64::FMADDSrrr, AArch64MachineCombinerPattern::FNMADD);
8292 }
8293
8294 return false;
8295}
8296
8297/// Return true when a code sequence can improve throughput. It
8298/// should be called only for instructions in loops.
8299/// \param Pattern - combiner pattern
8301 switch (Pattern) {
8302 default:
8303 break;
8409 return true;
8410 } // end switch (Pattern)
8411 return false;
8412}
8413
8414/// Find other MI combine patterns.
8416 SmallVectorImpl<unsigned> &Patterns) {
8417 // A - (B + C) ==> (A - B) - C or (A - C) - B
8418 unsigned Opc = Root.getOpcode();
8419 MachineBasicBlock &MBB = *Root.getParent();
8420
8421 switch (Opc) {
8422 case AArch64::SUBWrr:
8423 case AArch64::SUBSWrr:
8424 case AArch64::SUBXrr:
8425 case AArch64::SUBSXrr:
8426 // Found candidate root.
8427 break;
8428 default:
8429 return false;
8430 }
8431
8433 Root.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) ==
8434 -1)
8435 return false;
8436
8437 if (canCombine(MBB, Root.getOperand(2), AArch64::ADDWrr) ||
8438 canCombine(MBB, Root.getOperand(2), AArch64::ADDSWrr) ||
8439 canCombine(MBB, Root.getOperand(2), AArch64::ADDXrr) ||
8440 canCombine(MBB, Root.getOperand(2), AArch64::ADDSXrr)) {
8443 return true;
8444 }
8445
8446 return false;
8447}
8448
8449/// Check if the given instruction forms a gather load pattern that can be
8450/// optimized for better Memory-Level Parallelism (MLP). This function
8451/// identifies chains of NEON lane load instructions that load data from
8452/// different memory addresses into individual lanes of a 128-bit vector
8453/// register, then attempts to split the pattern into parallel loads to break
8454/// the serial dependency between instructions.
8455///
8456/// Pattern Matched:
8457/// Initial scalar load -> SUBREG_TO_REG (lane 0) -> LD1i* (lane 1) ->
8458/// LD1i* (lane 2) -> ... -> LD1i* (lane N-1, Root)
8459///
8460/// Transformed Into:
8461/// Two parallel vector loads using fewer lanes each, followed by ZIP1v2i64
8462/// to combine the results, enabling better memory-level parallelism.
8463///
8464/// Supported Element Types:
8465/// - 32-bit elements (LD1i32, 4 lanes total)
8466/// - 16-bit elements (LD1i16, 8 lanes total)
8467/// - 8-bit elements (LD1i8, 16 lanes total)
8469 SmallVectorImpl<unsigned> &Patterns,
8470 unsigned LoadLaneOpCode, unsigned NumLanes) {
8471 const MachineFunction *MF = Root.getMF();
8472
8473 // Early exit if optimizing for size.
8474 if (MF->getFunction().hasMinSize())
8475 return false;
8476
8477 const MachineRegisterInfo &MRI = MF->getRegInfo();
8479
8480 // The root of the pattern must load into the last lane of the vector.
8481 if (Root.getOperand(2).getImm() != NumLanes - 1)
8482 return false;
8483
8484 // Check that we have load into all lanes except lane 0.
8485 // For each load we also want to check that:
8486 // 1. It has a single non-debug use (since we will be replacing the virtual
8487 // register)
8488 // 2. That the addressing mode only uses a single pointer operand
8489 auto *CurrInstr = MRI.getUniqueVRegDef(Root.getOperand(1).getReg());
8490 auto Range = llvm::seq<unsigned>(1, NumLanes - 1);
8491 SmallSet<unsigned, 16> RemainingLanes(Range.begin(), Range.end());
8493 while (!RemainingLanes.empty() && CurrInstr &&
8494 CurrInstr->getOpcode() == LoadLaneOpCode &&
8495 MRI.hasOneNonDBGUse(CurrInstr->getOperand(0).getReg()) &&
8496 CurrInstr->getNumOperands() == 4) {
8497 RemainingLanes.erase(CurrInstr->getOperand(2).getImm());
8498 LoadInstrs.push_back(CurrInstr);
8499 CurrInstr = MRI.getUniqueVRegDef(CurrInstr->getOperand(1).getReg());
8500 }
8501
8502 // Check that we have found a match for lanes N-1.. 1.
8503 if (!RemainingLanes.empty())
8504 return false;
8505
8506 // Match the SUBREG_TO_REG sequence.
8507 if (CurrInstr->getOpcode() != TargetOpcode::SUBREG_TO_REG)
8508 return false;
8509
8510 // Verify that the subreg to reg loads an integer into the first lane.
8511 auto Lane0LoadReg = CurrInstr->getOperand(1).getReg();
8512 unsigned SingleLaneSizeInBits = 128 / NumLanes;
8513 if (TRI->getRegSizeInBits(Lane0LoadReg, MRI) != SingleLaneSizeInBits)
8514 return false;
8515
8516 // Verify that it also has a single non debug use.
8517 if (!MRI.hasOneNonDBGUse(Lane0LoadReg))
8518 return false;
8519
8520 LoadInstrs.push_back(MRI.getUniqueVRegDef(Lane0LoadReg));
8521
8522 // If there is any chance of aliasing, do not apply the pattern.
8523 // Walk backward through the MBB starting from Root.
8524 // Exit early if we've encountered all load instructions or hit the search
8525 // limit.
8526 auto MBBItr = Root.getIterator();
8527 unsigned RemainingSteps = GatherOptSearchLimit;
8528 SmallPtrSet<const MachineInstr *, 16> RemainingLoadInstrs;
8529 RemainingLoadInstrs.insert(LoadInstrs.begin(), LoadInstrs.end());
8530 const MachineBasicBlock *MBB = Root.getParent();
8531
8532 for (; MBBItr != MBB->begin() && RemainingSteps > 0 &&
8533 !RemainingLoadInstrs.empty();
8534 --MBBItr, --RemainingSteps) {
8535 const MachineInstr &CurrInstr = *MBBItr;
8536
8537 // Remove this instruction from remaining loads if it's one we're tracking.
8538 RemainingLoadInstrs.erase(&CurrInstr);
8539
8540 // Check for potential aliasing with any of the load instructions to
8541 // optimize.
8542 if (CurrInstr.isLoadFoldBarrier())
8543 return false;
8544 }
8545
8546 // If we hit the search limit without finding all load instructions,
8547 // don't match the pattern.
8548 if (RemainingSteps == 0 && !RemainingLoadInstrs.empty())
8549 return false;
8550
8551 switch (NumLanes) {
8552 case 4:
8554 break;
8555 case 8:
8557 break;
8558 case 16:
8560 break;
8561 default:
8562 llvm_unreachable("Got bad number of lanes for gather pattern.");
8563 }
8564
8565 return true;
8566}
8567
8568/// Search for patterns of LD instructions we can optimize.
8570 SmallVectorImpl<unsigned> &Patterns) {
8571
8572 // The pattern searches for loads into single lanes.
8573 switch (Root.getOpcode()) {
8574 case AArch64::LD1i32:
8575 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 4);
8576 case AArch64::LD1i16:
8577 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 8);
8578 case AArch64::LD1i8:
8579 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 16);
8580 default:
8581 return false;
8582 }
8583}
8584
8585/// Generate optimized instruction sequence for gather load patterns to improve
8586/// Memory-Level Parallelism (MLP). This function transforms a chain of
8587/// sequential NEON lane loads into parallel vector loads that can execute
8588/// concurrently.
8589static void
8593 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
8594 unsigned Pattern, unsigned NumLanes) {
8595 MachineFunction &MF = *Root.getParent()->getParent();
8596 MachineRegisterInfo &MRI = MF.getRegInfo();
8598
8599 // Gather the initial load instructions to build the pattern.
8600 SmallVector<MachineInstr *, 16> LoadToLaneInstrs;
8601 MachineInstr *CurrInstr = &Root;
8602 for (unsigned i = 0; i < NumLanes - 1; ++i) {
8603 LoadToLaneInstrs.push_back(CurrInstr);
8604 CurrInstr = MRI.getUniqueVRegDef(CurrInstr->getOperand(1).getReg());
8605 }
8606
8607 // Sort the load instructions according to the lane.
8608 llvm::sort(LoadToLaneInstrs,
8609 [](const MachineInstr *A, const MachineInstr *B) {
8610 return A->getOperand(2).getImm() > B->getOperand(2).getImm();
8611 });
8612
8613 MachineInstr *SubregToReg = CurrInstr;
8614 LoadToLaneInstrs.push_back(
8615 MRI.getUniqueVRegDef(SubregToReg->getOperand(1).getReg()));
8616 auto LoadToLaneInstrsAscending = llvm::reverse(LoadToLaneInstrs);
8617
8618 const TargetRegisterClass *FPR128RegClass =
8619 MRI.getRegClass(Root.getOperand(0).getReg());
8620
8621 // Helper lambda to create a LD1 instruction.
8622 auto CreateLD1Instruction = [&](MachineInstr *OriginalInstr,
8623 Register SrcRegister, unsigned Lane,
8624 Register OffsetRegister,
8625 bool OffsetRegisterKillState) {
8626 auto NewRegister = MRI.createVirtualRegister(FPR128RegClass);
8627 MachineInstrBuilder LoadIndexIntoRegister =
8628 BuildMI(MF, MIMetadata(*OriginalInstr), TII->get(Root.getOpcode()),
8629 NewRegister)
8630 .addReg(SrcRegister)
8631 .addImm(Lane)
8632 .addReg(OffsetRegister, getKillRegState(OffsetRegisterKillState))
8633 .setMemRefs(OriginalInstr->memoperands());
8634 InstrIdxForVirtReg.insert(std::make_pair(NewRegister, InsInstrs.size()));
8635 InsInstrs.push_back(LoadIndexIntoRegister);
8636 return NewRegister;
8637 };
8638
8639 // Helper to create load instruction based on the NumLanes in the NEON
8640 // register we are rewriting.
8641 auto CreateLDRInstruction =
8642 [&](unsigned NumLanes, Register DestReg, Register OffsetReg,
8644 unsigned Opcode;
8645 switch (NumLanes) {
8646 case 4:
8647 Opcode = AArch64::LDRSui;
8648 break;
8649 case 8:
8650 Opcode = AArch64::LDRHui;
8651 break;
8652 case 16:
8653 Opcode = AArch64::LDRBui;
8654 break;
8655 default:
8657 "Got unsupported number of lanes in machine-combiner gather pattern");
8658 }
8659 // Immediate offset load
8660 return BuildMI(MF, MIMetadata(Root), TII->get(Opcode), DestReg)
8661 .addReg(OffsetReg)
8662 .addImm(0)
8663 .setMemRefs(MMOs);
8664 };
8665
8666 // Load the remaining lanes into register 0.
8667 auto LanesToLoadToReg0 =
8668 llvm::make_range(LoadToLaneInstrsAscending.begin() + 1,
8669 LoadToLaneInstrsAscending.begin() + NumLanes / 2);
8670 Register PrevReg = SubregToReg->getOperand(0).getReg();
8671 for (auto [Index, LoadInstr] : llvm::enumerate(LanesToLoadToReg0)) {
8672 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8673 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8674 OffsetRegOperand.getReg(),
8675 OffsetRegOperand.isKill());
8676 DelInstrs.push_back(LoadInstr);
8677 }
8678 Register LastLoadReg0 = PrevReg;
8679
8680 // First load into register 1. Perform an integer load to zero out the upper
8681 // lanes in a single instruction.
8682 MachineInstr *Lane0Load = *LoadToLaneInstrsAscending.begin();
8683 MachineInstr *OriginalSplitLoad =
8684 *std::next(LoadToLaneInstrsAscending.begin(), NumLanes / 2);
8685 Register DestRegForMiddleIndex = MRI.createVirtualRegister(
8686 MRI.getRegClass(Lane0Load->getOperand(0).getReg()));
8687
8688 const MachineOperand &OriginalSplitToLoadOffsetOperand =
8689 OriginalSplitLoad->getOperand(3);
8690 MachineInstrBuilder MiddleIndexLoadInstr =
8691 CreateLDRInstruction(NumLanes, DestRegForMiddleIndex,
8692 OriginalSplitToLoadOffsetOperand.getReg(),
8693 OriginalSplitLoad->memoperands());
8694
8695 InstrIdxForVirtReg.insert(
8696 std::make_pair(DestRegForMiddleIndex, InsInstrs.size()));
8697 InsInstrs.push_back(MiddleIndexLoadInstr);
8698 DelInstrs.push_back(OriginalSplitLoad);
8699
8700 // Subreg To Reg instruction for register 1.
8701 Register DestRegForSubregToReg = MRI.createVirtualRegister(FPR128RegClass);
8702 unsigned SubregType;
8703 switch (NumLanes) {
8704 case 4:
8705 SubregType = AArch64::ssub;
8706 break;
8707 case 8:
8708 SubregType = AArch64::hsub;
8709 break;
8710 case 16:
8711 SubregType = AArch64::bsub;
8712 break;
8713 default:
8715 "Got invalid NumLanes for machine-combiner gather pattern");
8716 }
8717
8718 auto SubRegToRegInstr =
8719 BuildMI(MF, MIMetadata(Root), TII->get(SubregToReg->getOpcode()),
8720 DestRegForSubregToReg)
8721 .addReg(DestRegForMiddleIndex, getKillRegState(true))
8722 .addImm(SubregType);
8723 InstrIdxForVirtReg.insert(
8724 std::make_pair(DestRegForSubregToReg, InsInstrs.size()));
8725 InsInstrs.push_back(SubRegToRegInstr);
8726
8727 // Load remaining lanes into register 1.
8728 auto LanesToLoadToReg1 =
8729 llvm::make_range(LoadToLaneInstrsAscending.begin() + NumLanes / 2 + 1,
8730 LoadToLaneInstrsAscending.end());
8731 PrevReg = SubRegToRegInstr->getOperand(0).getReg();
8732 for (auto [Index, LoadInstr] : llvm::enumerate(LanesToLoadToReg1)) {
8733 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8734 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8735 OffsetRegOperand.getReg(),
8736 OffsetRegOperand.isKill());
8737
8738 // Do not add the last reg to DelInstrs - it will be removed later.
8739 if (Index == NumLanes / 2 - 2) {
8740 break;
8741 }
8742 DelInstrs.push_back(LoadInstr);
8743 }
8744 Register LastLoadReg1 = PrevReg;
8745
8746 // Create the final zip instruction to combine the results.
8747 MachineInstrBuilder ZipInstr =
8748 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::ZIP1v2i64),
8749 Root.getOperand(0).getReg())
8750 .addReg(LastLoadReg0)
8751 .addReg(LastLoadReg1);
8752 InsInstrs.push_back(ZipInstr);
8753}
8754
8768
8769/// Return true when there is potentially a faster code sequence for an
8770/// instruction chain ending in \p Root. All potential patterns are listed in
8771/// the \p Pattern vector. Pattern should be sorted in priority order since the
8772/// pattern evaluator stops checking as soon as it finds a faster sequence.
8773
8774bool AArch64InstrInfo::getMachineCombinerPatterns(
8775 MachineInstr &Root, SmallVectorImpl<unsigned> &Patterns,
8776 bool DoRegPressureReduce) const {
8777 // Integer patterns
8778 if (getMaddPatterns(Root, Patterns))
8779 return true;
8780 // Floating point patterns
8781 if (getFMULPatterns(Root, Patterns))
8782 return true;
8783 if (getFMAPatterns(Root, Patterns))
8784 return true;
8785 if (getFNEGPatterns(Root, Patterns))
8786 return true;
8787
8788 // Other patterns
8789 if (getMiscPatterns(Root, Patterns))
8790 return true;
8791
8792 // Load patterns
8793 if (getLoadPatterns(Root, Patterns))
8794 return true;
8795
8796 return TargetInstrInfo::getMachineCombinerPatterns(Root, Patterns,
8797 DoRegPressureReduce);
8798}
8799
8801/// genFusedMultiply - Generate fused multiply instructions.
8802/// This function supports both integer and floating point instructions.
8803/// A typical example:
8804/// F|MUL I=A,B,0
8805/// F|ADD R,I,C
8806/// ==> F|MADD R,A,B,C
8807/// \param MF Containing MachineFunction
8808/// \param MRI Register information
8809/// \param TII Target information
8810/// \param Root is the F|ADD instruction
8811/// \param [out] InsInstrs is a vector of machine instructions and will
8812/// contain the generated madd instruction
8813/// \param IdxMulOpd is index of operand in Root that is the result of
8814/// the F|MUL. In the example above IdxMulOpd is 1.
8815/// \param MaddOpc the opcode fo the f|madd instruction
8816/// \param RC Register class of operands
8817/// \param kind of fma instruction (addressing mode) to be generated
8818/// \param ReplacedAddend is the result register from the instruction
8819/// replacing the non-combined operand, if any.
8820static MachineInstr *
8822 const TargetInstrInfo *TII, MachineInstr &Root,
8823 SmallVectorImpl<MachineInstr *> &InsInstrs, unsigned IdxMulOpd,
8824 unsigned MaddOpc, const TargetRegisterClass *RC,
8826 const Register *ReplacedAddend = nullptr) {
8827 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8828
8829 unsigned IdxOtherOpd = IdxMulOpd == 1 ? 2 : 1;
8830 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
8831 Register ResultReg = Root.getOperand(0).getReg();
8832 Register SrcReg0 = MUL->getOperand(1).getReg();
8833 bool Src0IsKill = MUL->getOperand(1).isKill();
8834 Register SrcReg1 = MUL->getOperand(2).getReg();
8835 bool Src1IsKill = MUL->getOperand(2).isKill();
8836
8837 Register SrcReg2;
8838 bool Src2IsKill;
8839 if (ReplacedAddend) {
8840 // If we just generated a new addend, we must be it's only use.
8841 SrcReg2 = *ReplacedAddend;
8842 Src2IsKill = true;
8843 } else {
8844 SrcReg2 = Root.getOperand(IdxOtherOpd).getReg();
8845 Src2IsKill = Root.getOperand(IdxOtherOpd).isKill();
8846 }
8847
8848 if (ResultReg.isVirtual())
8849 MRI.constrainRegClass(ResultReg, RC);
8850 if (SrcReg0.isVirtual())
8851 MRI.constrainRegClass(SrcReg0, RC);
8852 if (SrcReg1.isVirtual())
8853 MRI.constrainRegClass(SrcReg1, RC);
8854 if (SrcReg2.isVirtual())
8855 MRI.constrainRegClass(SrcReg2, RC);
8856
8858 if (kind == FMAInstKind::Default)
8859 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8860 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8861 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8862 .addReg(SrcReg2, getKillRegState(Src2IsKill));
8863 else if (kind == FMAInstKind::Indexed)
8864 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8865 .addReg(SrcReg2, getKillRegState(Src2IsKill))
8866 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8867 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8868 .addImm(MUL->getOperand(3).getImm());
8869 else if (kind == FMAInstKind::Accumulator)
8870 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8871 .addReg(SrcReg2, getKillRegState(Src2IsKill))
8872 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8873 .addReg(SrcReg1, getKillRegState(Src1IsKill));
8874 else
8875 assert(false && "Invalid FMA instruction kind \n");
8876 // Insert the MADD (MADD, FMA, FMS, FMLA, FMSL)
8877 InsInstrs.push_back(MIB);
8878 return MUL;
8879}
8880
8881static MachineInstr *
8883 const TargetInstrInfo *TII, MachineInstr &Root,
8885 MachineInstr *MAD = MRI.getUniqueVRegDef(Root.getOperand(1).getReg());
8886
8887 unsigned Opc = 0;
8888 const TargetRegisterClass *RC = MRI.getRegClass(MAD->getOperand(0).getReg());
8889 if (AArch64::FPR32RegClass.hasSubClassEq(RC))
8890 Opc = AArch64::FNMADDSrrr;
8891 else if (AArch64::FPR64RegClass.hasSubClassEq(RC))
8892 Opc = AArch64::FNMADDDrrr;
8893 else
8894 return nullptr;
8895
8896 Register ResultReg = Root.getOperand(0).getReg();
8897 Register SrcReg0 = MAD->getOperand(1).getReg();
8898 Register SrcReg1 = MAD->getOperand(2).getReg();
8899 Register SrcReg2 = MAD->getOperand(3).getReg();
8900 bool Src0IsKill = MAD->getOperand(1).isKill();
8901 bool Src1IsKill = MAD->getOperand(2).isKill();
8902 bool Src2IsKill = MAD->getOperand(3).isKill();
8903 if (ResultReg.isVirtual())
8904 MRI.constrainRegClass(ResultReg, RC);
8905 if (SrcReg0.isVirtual())
8906 MRI.constrainRegClass(SrcReg0, RC);
8907 if (SrcReg1.isVirtual())
8908 MRI.constrainRegClass(SrcReg1, RC);
8909 if (SrcReg2.isVirtual())
8910 MRI.constrainRegClass(SrcReg2, RC);
8911
8913 BuildMI(MF, MIMetadata(Root), TII->get(Opc), ResultReg)
8914 .addReg(SrcReg0, getKillRegState(Src0IsKill))
8915 .addReg(SrcReg1, getKillRegState(Src1IsKill))
8916 .addReg(SrcReg2, getKillRegState(Src2IsKill));
8917 InsInstrs.push_back(MIB);
8918
8919 return MAD;
8920}
8921
8922/// Fold (FMUL x (DUP y lane)) into (FMUL_indexed x y lane)
8923static MachineInstr *
8926 unsigned IdxDupOp, unsigned MulOpc,
8927 const TargetRegisterClass *RC, MachineRegisterInfo &MRI) {
8928 assert(((IdxDupOp == 1) || (IdxDupOp == 2)) &&
8929 "Invalid index of FMUL operand");
8930
8931 MachineFunction &MF = *Root.getMF();
8933
8934 MachineInstr *Dup =
8935 MF.getRegInfo().getUniqueVRegDef(Root.getOperand(IdxDupOp).getReg());
8936
8937 if (Dup->getOpcode() == TargetOpcode::COPY)
8938 Dup = MRI.getUniqueVRegDef(Dup->getOperand(1).getReg());
8939
8940 Register DupSrcReg = Dup->getOperand(1).getReg();
8941 MRI.clearKillFlags(DupSrcReg);
8942 MRI.constrainRegClass(DupSrcReg, RC);
8943
8944 unsigned DupSrcLane = Dup->getOperand(2).getImm();
8945
8946 unsigned IdxMulOp = IdxDupOp == 1 ? 2 : 1;
8947 MachineOperand &MulOp = Root.getOperand(IdxMulOp);
8948
8949 Register ResultReg = Root.getOperand(0).getReg();
8950
8952 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MulOpc), ResultReg)
8953 .add(MulOp)
8954 .addReg(DupSrcReg)
8955 .addImm(DupSrcLane);
8956
8957 InsInstrs.push_back(MIB);
8958 return &Root;
8959}
8960
8961/// genFusedMultiplyAcc - Helper to generate fused multiply accumulate
8962/// instructions.
8963///
8964/// \see genFusedMultiply
8968 unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC) {
8969 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
8971}
8972
8973/// genNeg - Helper to generate an intermediate negation of the second operand
8974/// of Root
8976 const TargetInstrInfo *TII, MachineInstr &Root,
8978 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
8979 unsigned MnegOpc, const TargetRegisterClass *RC) {
8980 Register NewVR = MRI.createVirtualRegister(RC);
8982 BuildMI(MF, MIMetadata(Root), TII->get(MnegOpc), NewVR)
8983 .add(Root.getOperand(2));
8984 InsInstrs.push_back(MIB);
8985
8986 assert(InstrIdxForVirtReg.empty());
8987 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
8988
8989 return NewVR;
8990}
8991
8992/// genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate
8993/// instructions with an additional negation of the accumulator
8997 DenseMap<Register, unsigned> &InstrIdxForVirtReg, unsigned IdxMulOpd,
8998 unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC) {
8999 assert(IdxMulOpd == 1);
9000
9001 Register NewVR =
9002 genNeg(MF, MRI, TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
9003 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
9004 FMAInstKind::Accumulator, &NewVR);
9005}
9006
9007/// genFusedMultiplyIdx - Helper to generate fused multiply accumulate
9008/// instructions.
9009///
9010/// \see genFusedMultiply
9014 unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC) {
9015 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
9017}
9018
9019/// genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate
9020/// instructions with an additional negation of the accumulator
9024 DenseMap<Register, unsigned> &InstrIdxForVirtReg, unsigned IdxMulOpd,
9025 unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC) {
9026 assert(IdxMulOpd == 1);
9027
9028 Register NewVR =
9029 genNeg(MF, MRI, TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
9030
9031 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
9032 FMAInstKind::Indexed, &NewVR);
9033}
9034
9035/// genMaddR - Generate madd instruction and combine mul and add using
9036/// an extra virtual register
9037/// Example - an ADD intermediate needs to be stored in a register:
9038/// MUL I=A,B,0
9039/// ADD R,I,Imm
9040/// ==> ORR V, ZR, Imm
9041/// ==> MADD R,A,B,V
9042/// \param MF Containing MachineFunction
9043/// \param MRI Register information
9044/// \param TII Target information
9045/// \param Root is the ADD instruction
9046/// \param [out] InsInstrs is a vector of machine instructions and will
9047/// contain the generated madd instruction
9048/// \param IdxMulOpd is index of operand in Root that is the result of
9049/// the MUL. In the example above IdxMulOpd is 1.
9050/// \param MaddOpc the opcode fo the madd instruction
9051/// \param VR is a virtual register that holds the value of an ADD operand
9052/// (V in the example above).
9053/// \param RC Register class of operands
9055 const TargetInstrInfo *TII, MachineInstr &Root,
9057 unsigned IdxMulOpd, unsigned MaddOpc, unsigned VR,
9058 const TargetRegisterClass *RC) {
9059 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
9060
9061 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
9062 Register ResultReg = Root.getOperand(0).getReg();
9063 Register SrcReg0 = MUL->getOperand(1).getReg();
9064 bool Src0IsKill = MUL->getOperand(1).isKill();
9065 Register SrcReg1 = MUL->getOperand(2).getReg();
9066 bool Src1IsKill = MUL->getOperand(2).isKill();
9067
9068 if (ResultReg.isVirtual())
9069 MRI.constrainRegClass(ResultReg, RC);
9070 if (SrcReg0.isVirtual())
9071 MRI.constrainRegClass(SrcReg0, RC);
9072 if (SrcReg1.isVirtual())
9073 MRI.constrainRegClass(SrcReg1, RC);
9075 MRI.constrainRegClass(VR, RC);
9076
9078 BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
9079 .addReg(SrcReg0, getKillRegState(Src0IsKill))
9080 .addReg(SrcReg1, getKillRegState(Src1IsKill))
9081 .addReg(VR);
9082 // Insert the MADD
9083 InsInstrs.push_back(MIB);
9084 return MUL;
9085}
9086
9087/// Do the following transformation
9088/// A - (B + C) ==> (A - B) - C
9089/// A - (B + C) ==> (A - C) - B
9091 const TargetInstrInfo *TII, MachineInstr &Root,
9094 unsigned IdxOpd1,
9095 DenseMap<Register, unsigned> &InstrIdxForVirtReg) {
9096 assert(IdxOpd1 == 1 || IdxOpd1 == 2);
9097 unsigned IdxOtherOpd = IdxOpd1 == 1 ? 2 : 1;
9098 MachineInstr *AddMI = MRI.getUniqueVRegDef(Root.getOperand(2).getReg());
9099
9100 Register ResultReg = Root.getOperand(0).getReg();
9101 Register RegA = Root.getOperand(1).getReg();
9102 bool RegAIsKill = Root.getOperand(1).isKill();
9103 Register RegB = AddMI->getOperand(IdxOpd1).getReg();
9104 bool RegBIsKill = AddMI->getOperand(IdxOpd1).isKill();
9105 Register RegC = AddMI->getOperand(IdxOtherOpd).getReg();
9106 bool RegCIsKill = AddMI->getOperand(IdxOtherOpd).isKill();
9107 Register NewVR =
9109
9110 unsigned Opcode = Root.getOpcode();
9111 if (Opcode == AArch64::SUBSWrr)
9112 Opcode = AArch64::SUBWrr;
9113 else if (Opcode == AArch64::SUBSXrr)
9114 Opcode = AArch64::SUBXrr;
9115 else
9116 assert((Opcode == AArch64::SUBWrr || Opcode == AArch64::SUBXrr) &&
9117 "Unexpected instruction opcode.");
9118
9119 uint32_t Flags = Root.mergeFlagsWith(*AddMI);
9120 Flags &= ~MachineInstr::NoSWrap;
9121 Flags &= ~MachineInstr::NoUWrap;
9122
9123 MachineInstrBuilder MIB1 =
9124 BuildMI(MF, MIMetadata(Root), TII->get(Opcode), NewVR)
9125 .addReg(RegA, getKillRegState(RegAIsKill))
9126 .addReg(RegB, getKillRegState(RegBIsKill))
9127 .setMIFlags(Flags);
9128 MachineInstrBuilder MIB2 =
9129 BuildMI(MF, MIMetadata(Root), TII->get(Opcode), ResultReg)
9130 .addReg(NewVR, getKillRegState(true))
9131 .addReg(RegC, getKillRegState(RegCIsKill))
9132 .setMIFlags(Flags);
9133
9134 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9135 InsInstrs.push_back(MIB1);
9136 InsInstrs.push_back(MIB2);
9137 DelInstrs.push_back(AddMI);
9138 DelInstrs.push_back(&Root);
9139}
9140
9141unsigned AArch64InstrInfo::getReduceOpcodeForAccumulator(
9142 unsigned int AccumulatorOpCode) const {
9143 switch (AccumulatorOpCode) {
9144 case AArch64::UABALB_ZZZ_D:
9145 case AArch64::SABALB_ZZZ_D:
9146 case AArch64::UABALT_ZZZ_D:
9147 case AArch64::SABALT_ZZZ_D:
9148 return AArch64::ADD_ZZZ_D;
9149 case AArch64::UABALB_ZZZ_H:
9150 case AArch64::SABALB_ZZZ_H:
9151 case AArch64::UABALT_ZZZ_H:
9152 case AArch64::SABALT_ZZZ_H:
9153 return AArch64::ADD_ZZZ_H;
9154 case AArch64::UABALB_ZZZ_S:
9155 case AArch64::SABALB_ZZZ_S:
9156 case AArch64::UABALT_ZZZ_S:
9157 case AArch64::SABALT_ZZZ_S:
9158 return AArch64::ADD_ZZZ_S;
9159 case AArch64::UABALv16i8_v8i16:
9160 case AArch64::SABALv8i8_v8i16:
9161 case AArch64::SABAv8i16:
9162 case AArch64::UABAv8i16:
9163 return AArch64::ADDv8i16;
9164 case AArch64::SABALv2i32_v2i64:
9165 case AArch64::UABALv2i32_v2i64:
9166 case AArch64::SABALv4i32_v2i64:
9167 return AArch64::ADDv2i64;
9168 case AArch64::UABALv4i16_v4i32:
9169 case AArch64::SABALv4i16_v4i32:
9170 case AArch64::SABALv8i16_v4i32:
9171 case AArch64::SABAv4i32:
9172 case AArch64::UABAv4i32:
9173 return AArch64::ADDv4i32;
9174 case AArch64::UABALv4i32_v2i64:
9175 return AArch64::ADDv2i64;
9176 case AArch64::UABALv8i16_v4i32:
9177 return AArch64::ADDv4i32;
9178 case AArch64::UABALv8i8_v8i16:
9179 case AArch64::SABALv16i8_v8i16:
9180 return AArch64::ADDv8i16;
9181 case AArch64::UABAv16i8:
9182 case AArch64::SABAv16i8:
9183 return AArch64::ADDv16i8;
9184 case AArch64::UABAv4i16:
9185 case AArch64::SABAv4i16:
9186 return AArch64::ADDv4i16;
9187 case AArch64::UABAv2i32:
9188 case AArch64::SABAv2i32:
9189 return AArch64::ADDv2i32;
9190 case AArch64::UABAv8i8:
9191 case AArch64::SABAv8i8:
9192 return AArch64::ADDv8i8;
9193 default:
9194 llvm_unreachable("Unknown accumulator opcode");
9195 }
9196}
9197
9198/// When getMachineCombinerPatterns() finds potential patterns,
9199/// this function generates the instructions that could replace the
9200/// original code sequence
9201void AArch64InstrInfo::genAlternativeCodeSequence(
9202 MachineInstr &Root, unsigned Pattern,
9205 DenseMap<Register, unsigned> &InstrIdxForVirtReg) const {
9206 MachineBasicBlock &MBB = *Root.getParent();
9207 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9208 MachineFunction &MF = *MBB.getParent();
9209 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
9210
9211 MachineInstr *MUL = nullptr;
9212 const TargetRegisterClass *RC;
9213 unsigned Opc;
9214 switch (Pattern) {
9215 default:
9216 // Reassociate instructions.
9217 TargetInstrInfo::genAlternativeCodeSequence(Root, Pattern, InsInstrs,
9218 DelInstrs, InstrIdxForVirtReg);
9219 return;
9221 // A - (B + C)
9222 // ==> (A - B) - C
9223 genSubAdd2SubSub(MF, MRI, TII, Root, InsInstrs, DelInstrs, 1,
9224 InstrIdxForVirtReg);
9225 return;
9227 // A - (B + C)
9228 // ==> (A - C) - B
9229 genSubAdd2SubSub(MF, MRI, TII, Root, InsInstrs, DelInstrs, 2,
9230 InstrIdxForVirtReg);
9231 return;
9234 // MUL I=A,B,0
9235 // ADD R,I,C
9236 // ==> MADD R,A,B,C
9237 // --- Create(MADD);
9239 Opc = AArch64::MADDWrrr;
9240 RC = &AArch64::GPR32RegClass;
9241 } else {
9242 Opc = AArch64::MADDXrrr;
9243 RC = &AArch64::GPR64RegClass;
9244 }
9245 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9246 break;
9249 // MUL I=A,B,0
9250 // ADD R,C,I
9251 // ==> MADD R,A,B,C
9252 // --- Create(MADD);
9254 Opc = AArch64::MADDWrrr;
9255 RC = &AArch64::GPR32RegClass;
9256 } else {
9257 Opc = AArch64::MADDXrrr;
9258 RC = &AArch64::GPR64RegClass;
9259 }
9260 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9261 break;
9266 // MUL I=A,B,0
9267 // ADD/SUB R,I,Imm
9268 // ==> MOV V, Imm/-Imm
9269 // ==> MADD R,A,B,V
9270 // --- Create(MADD);
9271 const TargetRegisterClass *RC;
9272 unsigned BitSize, MovImm;
9275 MovImm = AArch64::MOVi32imm;
9276 RC = &AArch64::GPR32spRegClass;
9277 BitSize = 32;
9278 Opc = AArch64::MADDWrrr;
9279 RC = &AArch64::GPR32RegClass;
9280 } else {
9281 MovImm = AArch64::MOVi64imm;
9282 RC = &AArch64::GPR64spRegClass;
9283 BitSize = 64;
9284 Opc = AArch64::MADDXrrr;
9285 RC = &AArch64::GPR64RegClass;
9286 }
9287 Register NewVR = MRI.createVirtualRegister(RC);
9288 uint64_t Imm = Root.getOperand(2).getImm();
9289
9290 if (Root.getOperand(3).isImm()) {
9291 unsigned Val = Root.getOperand(3).getImm();
9292 Imm = Imm << Val;
9293 }
9294 bool IsSub = Pattern == AArch64MachineCombinerPattern::MULSUBWI_OP1 ||
9296 uint64_t UImm = SignExtend64(IsSub ? -Imm : Imm, BitSize);
9297 // Check that the immediate can be composed via a single instruction.
9299 AArch64_IMM::expandMOVImm(UImm, BitSize, Insn);
9300 if (Insn.size() != 1)
9301 return;
9302 MachineInstrBuilder MIB1 =
9303 BuildMI(MF, MIMetadata(Root), TII->get(MovImm), NewVR)
9304 .addImm(IsSub ? -Imm : Imm);
9305 InsInstrs.push_back(MIB1);
9306 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9307 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
9308 break;
9309 }
9312 // MUL I=A,B,0
9313 // SUB R,I, C
9314 // ==> SUB V, 0, C
9315 // ==> MADD R,A,B,V // = -C + A*B
9316 // --- Create(MADD);
9317 const TargetRegisterClass *SubRC;
9318 unsigned SubOpc, ZeroReg;
9320 SubOpc = AArch64::SUBWrr;
9321 SubRC = &AArch64::GPR32spRegClass;
9322 ZeroReg = AArch64::WZR;
9323 Opc = AArch64::MADDWrrr;
9324 RC = &AArch64::GPR32RegClass;
9325 } else {
9326 SubOpc = AArch64::SUBXrr;
9327 SubRC = &AArch64::GPR64spRegClass;
9328 ZeroReg = AArch64::XZR;
9329 Opc = AArch64::MADDXrrr;
9330 RC = &AArch64::GPR64RegClass;
9331 }
9332 Register NewVR = MRI.createVirtualRegister(SubRC);
9333 // SUB NewVR, 0, C
9334 MachineInstrBuilder MIB1 =
9335 BuildMI(MF, MIMetadata(Root), TII->get(SubOpc), NewVR)
9336 .addReg(ZeroReg)
9337 .add(Root.getOperand(2));
9338 InsInstrs.push_back(MIB1);
9339 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9340 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
9341 break;
9342 }
9345 // MUL I=A,B,0
9346 // SUB R,C,I
9347 // ==> MSUB R,A,B,C (computes C - A*B)
9348 // --- Create(MSUB);
9350 Opc = AArch64::MSUBWrrr;
9351 RC = &AArch64::GPR32RegClass;
9352 } else {
9353 Opc = AArch64::MSUBXrrr;
9354 RC = &AArch64::GPR64RegClass;
9355 }
9356 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9357 break;
9359 Opc = AArch64::MLAv8i8;
9360 RC = &AArch64::FPR64RegClass;
9361 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9362 break;
9364 Opc = AArch64::MLAv8i8;
9365 RC = &AArch64::FPR64RegClass;
9366 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9367 break;
9369 Opc = AArch64::MLAv16i8;
9370 RC = &AArch64::FPR128RegClass;
9371 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9372 break;
9374 Opc = AArch64::MLAv16i8;
9375 RC = &AArch64::FPR128RegClass;
9376 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9377 break;
9379 Opc = AArch64::MLAv4i16;
9380 RC = &AArch64::FPR64RegClass;
9381 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9382 break;
9384 Opc = AArch64::MLAv4i16;
9385 RC = &AArch64::FPR64RegClass;
9386 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9387 break;
9389 Opc = AArch64::MLAv8i16;
9390 RC = &AArch64::FPR128RegClass;
9391 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9392 break;
9394 Opc = AArch64::MLAv8i16;
9395 RC = &AArch64::FPR128RegClass;
9396 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9397 break;
9399 Opc = AArch64::MLAv2i32;
9400 RC = &AArch64::FPR64RegClass;
9401 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9402 break;
9404 Opc = AArch64::MLAv2i32;
9405 RC = &AArch64::FPR64RegClass;
9406 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9407 break;
9409 Opc = AArch64::MLAv4i32;
9410 RC = &AArch64::FPR128RegClass;
9411 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9412 break;
9414 Opc = AArch64::MLAv4i32;
9415 RC = &AArch64::FPR128RegClass;
9416 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9417 break;
9418
9420 Opc = AArch64::MLAv8i8;
9421 RC = &AArch64::FPR64RegClass;
9422 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9423 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i8,
9424 RC);
9425 break;
9427 Opc = AArch64::MLSv8i8;
9428 RC = &AArch64::FPR64RegClass;
9429 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9430 break;
9432 Opc = AArch64::MLAv16i8;
9433 RC = &AArch64::FPR128RegClass;
9434 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9435 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv16i8,
9436 RC);
9437 break;
9439 Opc = AArch64::MLSv16i8;
9440 RC = &AArch64::FPR128RegClass;
9441 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9442 break;
9444 Opc = AArch64::MLAv4i16;
9445 RC = &AArch64::FPR64RegClass;
9446 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9447 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i16,
9448 RC);
9449 break;
9451 Opc = AArch64::MLSv4i16;
9452 RC = &AArch64::FPR64RegClass;
9453 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9454 break;
9456 Opc = AArch64::MLAv8i16;
9457 RC = &AArch64::FPR128RegClass;
9458 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9459 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i16,
9460 RC);
9461 break;
9463 Opc = AArch64::MLSv8i16;
9464 RC = &AArch64::FPR128RegClass;
9465 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9466 break;
9468 Opc = AArch64::MLAv2i32;
9469 RC = &AArch64::FPR64RegClass;
9470 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9471 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv2i32,
9472 RC);
9473 break;
9475 Opc = AArch64::MLSv2i32;
9476 RC = &AArch64::FPR64RegClass;
9477 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9478 break;
9480 Opc = AArch64::MLAv4i32;
9481 RC = &AArch64::FPR128RegClass;
9482 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9483 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i32,
9484 RC);
9485 break;
9487 Opc = AArch64::MLSv4i32;
9488 RC = &AArch64::FPR128RegClass;
9489 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9490 break;
9491
9493 Opc = AArch64::MLAv4i16_indexed;
9494 RC = &AArch64::FPR64RegClass;
9495 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9496 break;
9498 Opc = AArch64::MLAv4i16_indexed;
9499 RC = &AArch64::FPR64RegClass;
9500 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9501 break;
9503 Opc = AArch64::MLAv8i16_indexed;
9504 RC = &AArch64::FPR128RegClass;
9505 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9506 break;
9508 Opc = AArch64::MLAv8i16_indexed;
9509 RC = &AArch64::FPR128RegClass;
9510 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9511 break;
9513 Opc = AArch64::MLAv2i32_indexed;
9514 RC = &AArch64::FPR64RegClass;
9515 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9516 break;
9518 Opc = AArch64::MLAv2i32_indexed;
9519 RC = &AArch64::FPR64RegClass;
9520 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9521 break;
9523 Opc = AArch64::MLAv4i32_indexed;
9524 RC = &AArch64::FPR128RegClass;
9525 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9526 break;
9528 Opc = AArch64::MLAv4i32_indexed;
9529 RC = &AArch64::FPR128RegClass;
9530 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9531 break;
9532
9534 Opc = AArch64::MLAv4i16_indexed;
9535 RC = &AArch64::FPR64RegClass;
9536 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9537 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i16,
9538 RC);
9539 break;
9541 Opc = AArch64::MLSv4i16_indexed;
9542 RC = &AArch64::FPR64RegClass;
9543 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9544 break;
9546 Opc = AArch64::MLAv8i16_indexed;
9547 RC = &AArch64::FPR128RegClass;
9548 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9549 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i16,
9550 RC);
9551 break;
9553 Opc = AArch64::MLSv8i16_indexed;
9554 RC = &AArch64::FPR128RegClass;
9555 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9556 break;
9558 Opc = AArch64::MLAv2i32_indexed;
9559 RC = &AArch64::FPR64RegClass;
9560 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9561 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv2i32,
9562 RC);
9563 break;
9565 Opc = AArch64::MLSv2i32_indexed;
9566 RC = &AArch64::FPR64RegClass;
9567 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9568 break;
9570 Opc = AArch64::MLAv4i32_indexed;
9571 RC = &AArch64::FPR128RegClass;
9572 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9573 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i32,
9574 RC);
9575 break;
9577 Opc = AArch64::MLSv4i32_indexed;
9578 RC = &AArch64::FPR128RegClass;
9579 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9580 break;
9581
9582 // Floating Point Support
9584 Opc = AArch64::FMADDHrrr;
9585 RC = &AArch64::FPR16RegClass;
9586 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9587 break;
9589 Opc = AArch64::FMADDSrrr;
9590 RC = &AArch64::FPR32RegClass;
9591 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9592 break;
9594 Opc = AArch64::FMADDDrrr;
9595 RC = &AArch64::FPR64RegClass;
9596 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9597 break;
9598
9600 Opc = AArch64::FMADDHrrr;
9601 RC = &AArch64::FPR16RegClass;
9602 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9603 break;
9605 Opc = AArch64::FMADDSrrr;
9606 RC = &AArch64::FPR32RegClass;
9607 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9608 break;
9610 Opc = AArch64::FMADDDrrr;
9611 RC = &AArch64::FPR64RegClass;
9612 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9613 break;
9614
9616 Opc = AArch64::FMLAv1i32_indexed;
9617 RC = &AArch64::FPR32RegClass;
9618 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9620 break;
9622 Opc = AArch64::FMLAv1i32_indexed;
9623 RC = &AArch64::FPR32RegClass;
9624 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9626 break;
9627
9629 Opc = AArch64::FMLAv1i64_indexed;
9630 RC = &AArch64::FPR64RegClass;
9631 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9633 break;
9635 Opc = AArch64::FMLAv1i64_indexed;
9636 RC = &AArch64::FPR64RegClass;
9637 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9639 break;
9640
9642 RC = &AArch64::FPR64RegClass;
9643 Opc = AArch64::FMLAv4i16_indexed;
9644 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9646 break;
9648 RC = &AArch64::FPR64RegClass;
9649 Opc = AArch64::FMLAv4f16;
9650 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9652 break;
9654 RC = &AArch64::FPR64RegClass;
9655 Opc = AArch64::FMLAv4i16_indexed;
9656 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9658 break;
9660 RC = &AArch64::FPR64RegClass;
9661 Opc = AArch64::FMLAv4f16;
9662 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9664 break;
9665
9668 RC = &AArch64::FPR64RegClass;
9670 Opc = AArch64::FMLAv2i32_indexed;
9671 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9673 } else {
9674 Opc = AArch64::FMLAv2f32;
9675 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9677 }
9678 break;
9681 RC = &AArch64::FPR64RegClass;
9683 Opc = AArch64::FMLAv2i32_indexed;
9684 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9686 } else {
9687 Opc = AArch64::FMLAv2f32;
9688 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9690 }
9691 break;
9692
9694 RC = &AArch64::FPR128RegClass;
9695 Opc = AArch64::FMLAv8i16_indexed;
9696 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9698 break;
9700 RC = &AArch64::FPR128RegClass;
9701 Opc = AArch64::FMLAv8f16;
9702 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9704 break;
9706 RC = &AArch64::FPR128RegClass;
9707 Opc = AArch64::FMLAv8i16_indexed;
9708 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9710 break;
9712 RC = &AArch64::FPR128RegClass;
9713 Opc = AArch64::FMLAv8f16;
9714 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9716 break;
9717
9720 RC = &AArch64::FPR128RegClass;
9722 Opc = AArch64::FMLAv2i64_indexed;
9723 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9725 } else {
9726 Opc = AArch64::FMLAv2f64;
9727 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9729 }
9730 break;
9733 RC = &AArch64::FPR128RegClass;
9735 Opc = AArch64::FMLAv2i64_indexed;
9736 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9738 } else {
9739 Opc = AArch64::FMLAv2f64;
9740 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9742 }
9743 break;
9744
9747 RC = &AArch64::FPR128RegClass;
9749 Opc = AArch64::FMLAv4i32_indexed;
9750 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9752 } else {
9753 Opc = AArch64::FMLAv4f32;
9754 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9756 }
9757 break;
9758
9761 RC = &AArch64::FPR128RegClass;
9763 Opc = AArch64::FMLAv4i32_indexed;
9764 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9766 } else {
9767 Opc = AArch64::FMLAv4f32;
9768 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9770 }
9771 break;
9772
9774 Opc = AArch64::FNMSUBHrrr;
9775 RC = &AArch64::FPR16RegClass;
9776 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9777 break;
9779 Opc = AArch64::FNMSUBSrrr;
9780 RC = &AArch64::FPR32RegClass;
9781 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9782 break;
9784 Opc = AArch64::FNMSUBDrrr;
9785 RC = &AArch64::FPR64RegClass;
9786 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9787 break;
9788
9790 Opc = AArch64::FNMADDHrrr;
9791 RC = &AArch64::FPR16RegClass;
9792 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9793 break;
9795 Opc = AArch64::FNMADDSrrr;
9796 RC = &AArch64::FPR32RegClass;
9797 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9798 break;
9800 Opc = AArch64::FNMADDDrrr;
9801 RC = &AArch64::FPR64RegClass;
9802 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9803 break;
9804
9806 Opc = AArch64::FMSUBHrrr;
9807 RC = &AArch64::FPR16RegClass;
9808 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9809 break;
9811 Opc = AArch64::FMSUBSrrr;
9812 RC = &AArch64::FPR32RegClass;
9813 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9814 break;
9816 Opc = AArch64::FMSUBDrrr;
9817 RC = &AArch64::FPR64RegClass;
9818 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9819 break;
9820
9822 Opc = AArch64::FMLSv1i32_indexed;
9823 RC = &AArch64::FPR32RegClass;
9824 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9826 break;
9827
9829 Opc = AArch64::FMLSv1i64_indexed;
9830 RC = &AArch64::FPR64RegClass;
9831 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9833 break;
9834
9837 RC = &AArch64::FPR64RegClass;
9838 Register NewVR = MRI.createVirtualRegister(RC);
9839 MachineInstrBuilder MIB1 =
9840 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv4f16), NewVR)
9841 .add(Root.getOperand(2));
9842 InsInstrs.push_back(MIB1);
9843 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9845 Opc = AArch64::FMLAv4f16;
9846 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9847 FMAInstKind::Accumulator, &NewVR);
9848 } else {
9849 Opc = AArch64::FMLAv4i16_indexed;
9850 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9851 FMAInstKind::Indexed, &NewVR);
9852 }
9853 break;
9854 }
9856 RC = &AArch64::FPR64RegClass;
9857 Opc = AArch64::FMLSv4f16;
9858 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9860 break;
9862 RC = &AArch64::FPR64RegClass;
9863 Opc = AArch64::FMLSv4i16_indexed;
9864 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9866 break;
9867
9870 RC = &AArch64::FPR64RegClass;
9872 Opc = AArch64::FMLSv2i32_indexed;
9873 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9875 } else {
9876 Opc = AArch64::FMLSv2f32;
9877 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9879 }
9880 break;
9881
9884 RC = &AArch64::FPR128RegClass;
9885 Register NewVR = MRI.createVirtualRegister(RC);
9886 MachineInstrBuilder MIB1 =
9887 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv8f16), NewVR)
9888 .add(Root.getOperand(2));
9889 InsInstrs.push_back(MIB1);
9890 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9892 Opc = AArch64::FMLAv8f16;
9893 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9894 FMAInstKind::Accumulator, &NewVR);
9895 } else {
9896 Opc = AArch64::FMLAv8i16_indexed;
9897 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9898 FMAInstKind::Indexed, &NewVR);
9899 }
9900 break;
9901 }
9903 RC = &AArch64::FPR128RegClass;
9904 Opc = AArch64::FMLSv8f16;
9905 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9907 break;
9909 RC = &AArch64::FPR128RegClass;
9910 Opc = AArch64::FMLSv8i16_indexed;
9911 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9913 break;
9914
9917 RC = &AArch64::FPR128RegClass;
9919 Opc = AArch64::FMLSv2i64_indexed;
9920 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9922 } else {
9923 Opc = AArch64::FMLSv2f64;
9924 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9926 }
9927 break;
9928
9931 RC = &AArch64::FPR128RegClass;
9933 Opc = AArch64::FMLSv4i32_indexed;
9934 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9936 } else {
9937 Opc = AArch64::FMLSv4f32;
9938 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9940 }
9941 break;
9944 RC = &AArch64::FPR64RegClass;
9945 Register NewVR = MRI.createVirtualRegister(RC);
9946 MachineInstrBuilder MIB1 =
9947 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv2f32), NewVR)
9948 .add(Root.getOperand(2));
9949 InsInstrs.push_back(MIB1);
9950 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9952 Opc = AArch64::FMLAv2i32_indexed;
9953 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9954 FMAInstKind::Indexed, &NewVR);
9955 } else {
9956 Opc = AArch64::FMLAv2f32;
9957 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9958 FMAInstKind::Accumulator, &NewVR);
9959 }
9960 break;
9961 }
9964 RC = &AArch64::FPR128RegClass;
9965 Register NewVR = MRI.createVirtualRegister(RC);
9966 MachineInstrBuilder MIB1 =
9967 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv4f32), NewVR)
9968 .add(Root.getOperand(2));
9969 InsInstrs.push_back(MIB1);
9970 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9972 Opc = AArch64::FMLAv4i32_indexed;
9973 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9974 FMAInstKind::Indexed, &NewVR);
9975 } else {
9976 Opc = AArch64::FMLAv4f32;
9977 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9978 FMAInstKind::Accumulator, &NewVR);
9979 }
9980 break;
9981 }
9984 RC = &AArch64::FPR128RegClass;
9985 Register NewVR = MRI.createVirtualRegister(RC);
9986 MachineInstrBuilder MIB1 =
9987 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv2f64), NewVR)
9988 .add(Root.getOperand(2));
9989 InsInstrs.push_back(MIB1);
9990 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9992 Opc = AArch64::FMLAv2i64_indexed;
9993 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9994 FMAInstKind::Indexed, &NewVR);
9995 } else {
9996 Opc = AArch64::FMLAv2f64;
9997 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9998 FMAInstKind::Accumulator, &NewVR);
9999 }
10000 break;
10001 }
10004 unsigned IdxDupOp =
10006 : 2;
10007 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv2i32_indexed,
10008 &AArch64::FPR128RegClass, MRI);
10009 break;
10010 }
10013 unsigned IdxDupOp =
10015 : 2;
10016 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv2i64_indexed,
10017 &AArch64::FPR128RegClass, MRI);
10018 break;
10019 }
10022 unsigned IdxDupOp =
10024 : 2;
10025 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv4i16_indexed,
10026 &AArch64::FPR128_loRegClass, MRI);
10027 break;
10028 }
10031 unsigned IdxDupOp =
10033 : 2;
10034 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv4i32_indexed,
10035 &AArch64::FPR128RegClass, MRI);
10036 break;
10037 }
10040 unsigned IdxDupOp =
10042 : 2;
10043 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv8i16_indexed,
10044 &AArch64::FPR128_loRegClass, MRI);
10045 break;
10046 }
10048 MUL = genFNegatedMAD(MF, MRI, TII, Root, InsInstrs);
10049 break;
10050 }
10052 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
10053 Pattern, 4);
10054 break;
10055 }
10057 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
10058 Pattern, 8);
10059 break;
10060 }
10062 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
10063 Pattern, 16);
10064 break;
10065 }
10066
10067 } // end switch (Pattern)
10068 // Record MUL and ADD/SUB for deletion
10069 if (MUL)
10070 DelInstrs.push_back(MUL);
10071 DelInstrs.push_back(&Root);
10072
10073 // Set the flags on the inserted instructions to be the merged flags of the
10074 // instructions that we have combined.
10075 uint32_t Flags = Root.getFlags();
10076 if (MUL)
10077 Flags = Root.mergeFlagsWith(*MUL);
10078 for (auto *MI : InsInstrs)
10079 MI->setFlags(Flags);
10080}
10081
10082/// Replace csincr-branch sequence by simple conditional branch
10083///
10084/// Examples:
10085/// 1. \code
10086/// csinc w9, wzr, wzr, <condition code>
10087/// tbnz w9, #0, 0x44
10088/// \endcode
10089/// to
10090/// \code
10091/// b.<inverted condition code>
10092/// \endcode
10093///
10094/// 2. \code
10095/// csinc w9, wzr, wzr, <condition code>
10096/// tbz w9, #0, 0x44
10097/// \endcode
10098/// to
10099/// \code
10100/// b.<condition code>
10101/// \endcode
10102///
10103/// Replace compare and branch sequence by TBZ/TBNZ instruction when the
10104/// compare's constant operand is power of 2.
10105///
10106/// Examples:
10107/// \code
10108/// and w8, w8, #0x400
10109/// cbnz w8, L1
10110/// \endcode
10111/// to
10112/// \code
10113/// tbnz w8, #10, L1
10114/// \endcode
10115///
10116/// \param MI Conditional Branch
10117/// \return True when the simple conditional branch is generated
10118///
10120 bool IsNegativeBranch = false;
10121 bool IsTestAndBranch = false;
10122 unsigned TargetBBInMI = 0;
10123 switch (MI.getOpcode()) {
10124 default:
10125 llvm_unreachable("Unknown branch instruction?");
10126 case AArch64::Bcc:
10127 case AArch64::CBWPri:
10128 case AArch64::CBXPri:
10129 case AArch64::CBBAssertExt:
10130 case AArch64::CBHAssertExt:
10131 case AArch64::CBWPrr:
10132 case AArch64::CBXPrr:
10133 return false;
10134 case AArch64::CBZW:
10135 case AArch64::CBZX:
10136 TargetBBInMI = 1;
10137 break;
10138 case AArch64::CBNZW:
10139 case AArch64::CBNZX:
10140 TargetBBInMI = 1;
10141 IsNegativeBranch = true;
10142 break;
10143 case AArch64::TBZW:
10144 case AArch64::TBZX:
10145 TargetBBInMI = 2;
10146 IsTestAndBranch = true;
10147 break;
10148 case AArch64::TBNZW:
10149 case AArch64::TBNZX:
10150 TargetBBInMI = 2;
10151 IsNegativeBranch = true;
10152 IsTestAndBranch = true;
10153 break;
10154 }
10155 // So we increment a zero register and test for bits other
10156 // than bit 0? Conservatively bail out in case the verifier
10157 // missed this case.
10158 if (IsTestAndBranch && MI.getOperand(1).getImm())
10159 return false;
10160
10161 // Find Definition.
10162 assert(MI.getParent() && "Incomplete machine instruction\n");
10163 MachineBasicBlock *MBB = MI.getParent();
10164 MachineFunction *MF = MBB->getParent();
10165 MachineRegisterInfo *MRI = &MF->getRegInfo();
10166 Register VReg = MI.getOperand(0).getReg();
10167 if (!VReg.isVirtual())
10168 return false;
10169
10170 MachineInstr *DefMI = MRI->getVRegDef(VReg);
10171 if (!DefMI)
10172 return false;
10173
10174 // Look through COPY instructions to find definition.
10175 while (DefMI->isCopy()) {
10176 Register CopyVReg = DefMI->getOperand(1).getReg();
10177 if (!CopyVReg.isVirtual())
10178 return false;
10179 if (!MRI->hasOneNonDBGUse(CopyVReg))
10180 return false;
10181 DefMI = MRI->getVRegDef(CopyVReg);
10182 if (!DefMI)
10183 return false;
10184 }
10185
10186 switch (DefMI->getOpcode()) {
10187 default:
10188 return false;
10189 // Fold AND into a TBZ/TBNZ if constant operand is power of 2.
10190 case AArch64::ANDWri:
10191 case AArch64::ANDXri: {
10192 if (IsTestAndBranch)
10193 return false;
10194 if (DefMI->getParent() != MBB)
10195 return false;
10196 if (!MRI->hasOneNonDBGUse(VReg))
10197 return false;
10198
10199 bool Is32Bit = (DefMI->getOpcode() == AArch64::ANDWri);
10200 uint64_t Mask = AArch64_AM::decodeLogicalImmediate(
10201 DefMI->getOperand(2).getImm(), Is32Bit ? 32 : 64);
10202 if (!isPowerOf2_64(Mask))
10203 return false;
10204
10205 MachineOperand &MO = DefMI->getOperand(1);
10206 Register NewReg = MO.getReg();
10207 if (!NewReg.isVirtual())
10208 return false;
10209
10210 if (!MRI->getVRegDef(NewReg))
10211 return false;
10212
10213 MachineBasicBlock &RefToMBB = *MBB;
10214 MachineBasicBlock *TBB = MI.getOperand(1).getMBB();
10215 DebugLoc DL = MI.getDebugLoc();
10216 unsigned Imm = Log2_64(Mask);
10217 unsigned Opc = (Imm < 32)
10218 ? (IsNegativeBranch ? AArch64::TBNZW : AArch64::TBZW)
10219 : (IsNegativeBranch ? AArch64::TBNZX : AArch64::TBZX);
10220 MachineInstr *NewMI = BuildMI(RefToMBB, MI, DL, get(Opc))
10221 .addReg(NewReg)
10222 .addImm(Imm)
10223 .addMBB(TBB);
10224 // Register lives on to the CBZ now.
10225 MO.setIsKill(false);
10226
10227 // For immediate smaller than 32, we need to use the 32-bit
10228 // variant (W) in all cases. Indeed the 64-bit variant does not
10229 // allow to encode them.
10230 // Therefore, if the input register is 64-bit, we need to take the
10231 // 32-bit sub-part.
10232 if (!Is32Bit && Imm < 32)
10233 NewMI->getOperand(0).setSubReg(AArch64::sub_32);
10234 MI.eraseFromParent();
10235 return true;
10236 }
10237 // Look for CSINC
10238 case AArch64::CSINCWr:
10239 case AArch64::CSINCXr: {
10240 if (!(DefMI->getOperand(1).getReg() == AArch64::WZR &&
10241 DefMI->getOperand(2).getReg() == AArch64::WZR) &&
10242 !(DefMI->getOperand(1).getReg() == AArch64::XZR &&
10243 DefMI->getOperand(2).getReg() == AArch64::XZR))
10244 return false;
10245
10246 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
10247 true) != -1)
10248 return false;
10249
10250 AArch64CC::CondCode CC = (AArch64CC::CondCode)DefMI->getOperand(3).getImm();
10251 // Convert only when the condition code is not modified between
10252 // the CSINC and the branch. The CC may be used by other
10253 // instructions in between.
10255 return false;
10256 MachineBasicBlock &RefToMBB = *MBB;
10257 MachineBasicBlock *TBB = MI.getOperand(TargetBBInMI).getMBB();
10258 DebugLoc DL = MI.getDebugLoc();
10259 if (IsNegativeBranch)
10261 BuildMI(RefToMBB, MI, DL, get(AArch64::Bcc)).addImm(CC).addMBB(TBB);
10262 MI.eraseFromParent();
10263 return true;
10264 }
10265 }
10266}
10267
10268std::pair<unsigned, unsigned>
10269AArch64InstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
10270 const unsigned Mask = AArch64II::MO_FRAGMENT;
10271 return std::make_pair(TF & Mask, TF & ~Mask);
10272}
10273
10275AArch64InstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
10276 using namespace AArch64II;
10277
10278 static const std::pair<unsigned, const char *> TargetFlags[] = {
10279 {MO_PAGE, "aarch64-page"}, {MO_PAGEOFF, "aarch64-pageoff"},
10280 {MO_G3, "aarch64-g3"}, {MO_G2, "aarch64-g2"},
10281 {MO_G1, "aarch64-g1"}, {MO_G0, "aarch64-g0"},
10282 {MO_HI12, "aarch64-hi12"}};
10283 return ArrayRef(TargetFlags);
10284}
10285
10287AArch64InstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
10288 using namespace AArch64II;
10289
10290 static const std::pair<unsigned, const char *> TargetFlags[] = {
10291 {MO_COFFSTUB, "aarch64-coffstub"},
10292 {MO_GOT, "aarch64-got"},
10293 {MO_NC, "aarch64-nc"},
10294 {MO_S, "aarch64-s"},
10295 {MO_TLS, "aarch64-tls"},
10296 {MO_DLLIMPORT, "aarch64-dllimport"},
10297 {MO_PREL, "aarch64-prel"},
10298 {MO_TAGGED, "aarch64-tagged"},
10299 {MO_ARM64EC_CALLMANGLE, "aarch64-arm64ec-callmangle"},
10300 };
10301 return ArrayRef(TargetFlags);
10302}
10303
10305AArch64InstrInfo::getSerializableMachineMemOperandTargetFlags() const {
10306 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10307 {{MOSuppressPair, "aarch64-suppress-pair"},
10308 {MOStridedAccess, "aarch64-strided-access"}};
10309 return ArrayRef(TargetFlags);
10310}
10311
10312/// Constants defining how certain sequences should be outlined.
10313/// This encompasses how an outlined function should be called, and what kind of
10314/// frame should be emitted for that outlined function.
10315///
10316/// \p MachineOutlinerDefault implies that the function should be called with
10317/// a save and restore of LR to the stack.
10318///
10319/// That is,
10320///
10321/// I1 Save LR OUTLINED_FUNCTION:
10322/// I2 --> BL OUTLINED_FUNCTION I1
10323/// I3 Restore LR I2
10324/// I3
10325/// RET
10326///
10327/// * Call construction overhead: 3 (save + BL + restore)
10328/// * Frame construction overhead: 1 (ret)
10329/// * Requires stack fixups? Yes
10330///
10331/// \p MachineOutlinerTailCall implies that the function is being created from
10332/// a sequence of instructions ending in a return.
10333///
10334/// That is,
10335///
10336/// I1 OUTLINED_FUNCTION:
10337/// I2 --> B OUTLINED_FUNCTION I1
10338/// RET I2
10339/// RET
10340///
10341/// * Call construction overhead: 1 (B)
10342/// * Frame construction overhead: 0 (Return included in sequence)
10343/// * Requires stack fixups? No
10344///
10345/// \p MachineOutlinerNoLRSave implies that the function should be called using
10346/// a BL instruction, but doesn't require LR to be saved and restored. This
10347/// happens when LR is known to be dead.
10348///
10349/// That is,
10350///
10351/// I1 OUTLINED_FUNCTION:
10352/// I2 --> BL OUTLINED_FUNCTION I1
10353/// I3 I2
10354/// I3
10355/// RET
10356///
10357/// * Call construction overhead: 1 (BL)
10358/// * Frame construction overhead: 1 (RET)
10359/// * Requires stack fixups? No
10360///
10361/// \p MachineOutlinerThunk implies that the function is being created from
10362/// a sequence of instructions ending in a call. The outlined function is
10363/// called with a BL instruction, and the outlined function tail-calls the
10364/// original call destination.
10365///
10366/// That is,
10367///
10368/// I1 OUTLINED_FUNCTION:
10369/// I2 --> BL OUTLINED_FUNCTION I1
10370/// BL f I2
10371/// B f
10372/// * Call construction overhead: 1 (BL)
10373/// * Frame construction overhead: 0
10374/// * Requires stack fixups? No
10375///
10376/// \p MachineOutlinerRegSave implies that the function should be called with a
10377/// save and restore of LR to an available register. This allows us to avoid
10378/// stack fixups. Note that this outlining variant is compatible with the
10379/// NoLRSave case.
10380///
10381/// That is,
10382///
10383/// I1 Save LR OUTLINED_FUNCTION:
10384/// I2 --> BL OUTLINED_FUNCTION I1
10385/// I3 Restore LR I2
10386/// I3
10387/// RET
10388///
10389/// * Call construction overhead: 3 (save + BL + restore)
10390/// * Frame construction overhead: 1 (ret)
10391/// * Requires stack fixups? No
10393 MachineOutlinerDefault, /// Emit a save, restore, call, and return.
10394 MachineOutlinerTailCall, /// Only emit a branch.
10395 MachineOutlinerNoLRSave, /// Emit a call and return.
10396 MachineOutlinerThunk, /// Emit a call and tail-call.
10397 MachineOutlinerRegSave /// Same as default, but save to a register.
10398};
10399
10405
10406/// Return true if the frame-record form of the outlined prologue is enabled for
10407/// the target of \p MF.
10408///
10409/// A non-leaf outlined function must save LR. On MachO, saving LR alone
10410/// (str x30) has no compact unwind encoding, so we get a large DWARF FDE
10411/// instead. Saving FP and LR as a frame record (stp x29, x30 ; mov x29, sp)
10412/// gets the small FRAME encoding, and costs one extra instruction.
10417
10418/// Return true if the outlined function in \p MBB should save FP and LR as a
10419/// frame record instead of saving LR alone.
10421 const MachineBasicBlock &MBB) {
10422 const MachineFunction &MF = *MBB.getParent();
10423
10424 // Only worth it if the function has unwind info to shrink.
10427 return false;
10428
10429 // Only safe if the outlined code never touches FP, since we overwrite it.
10431 for (const MachineInstr &MI : MBB.instrs())
10432 LRU.accumulate(MI);
10433 return LRU.available(AArch64::FP);
10434}
10435
10436/// Predict what the above will answer, for use while costing candidates. The
10437/// outlined function does not exist yet, so answer from \p RepeatedSequenceLocs
10438/// instead. This is only an estimate; buildOutlinedFrame() makes the call.
10440 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
10441 const TargetRegisterInfo &TRI) {
10442 if (!isCompactUnwindFrameRecordEnabled(*RepeatedSequenceLocs.front().getMF()))
10443 return false;
10444
10445 // The outlined function is nounwind only if every candidate is, so it has
10446 // unwind info if any candidate does.
10447 if (llvm::none_of(RepeatedSequenceLocs, [](outliner::Candidate &C) {
10448 const MachineFunction &MF = *C.getMF();
10449 return MF.getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF);
10450 }))
10451 return false;
10452
10453 // FP is free in the outlined function only if it is free in every candidate.
10454 return llvm::all_of(RepeatedSequenceLocs, [&TRI](outliner::Candidate &C) {
10455 return C.isAvailableInsideSeq(AArch64::FP, TRI);
10456 });
10457}
10458
10460AArch64InstrInfo::findRegisterToSaveLRTo(outliner::Candidate &C) const {
10461 MachineFunction *MF = C.getMF();
10462 const TargetRegisterInfo &TRI = *MF->getSubtarget().getRegisterInfo();
10463 const AArch64RegisterInfo *ARI =
10464 static_cast<const AArch64RegisterInfo *>(&TRI);
10465 // Check if there is an available register across the sequence that we can
10466 // use.
10467 for (unsigned Reg : AArch64::GPR64RegClass) {
10468 if (!ARI->isReservedReg(*MF, Reg) &&
10469 Reg != AArch64::LR && // LR is not reserved, but don't use it.
10470 Reg != AArch64::X16 && // X16 is not guaranteed to be preserved.
10471 Reg != AArch64::X17 && // Ditto for X17.
10472 C.isAvailableAcrossAndOutOfSeq(Reg, TRI) &&
10473 C.isAvailableInsideSeq(Reg, TRI))
10474 return Reg;
10475 }
10476 return Register();
10477}
10478
10479static bool
10481 const outliner::Candidate &b) {
10482 const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>();
10483 const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>();
10484
10485 return MFIa->getSignReturnAddressCondition() ==
10487}
10488
10489static bool
10491 const outliner::Candidate &b) {
10492 const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>();
10493 const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>();
10494
10495 return MFIa->shouldSignWithBKey() == MFIb->shouldSignWithBKey();
10496}
10497
10499 const outliner::Candidate &b) {
10500 const AArch64Subtarget &SubtargetA =
10502 const AArch64Subtarget &SubtargetB =
10503 b.getMF()->getSubtarget<AArch64Subtarget>();
10504 return SubtargetA.hasV8_3aOps() == SubtargetB.hasV8_3aOps();
10505}
10506
10507std::optional<std::unique_ptr<outliner::OutlinedFunction>>
10508AArch64InstrInfo::getOutliningCandidateInfo(
10509 const MachineModuleInfo &MMI,
10510 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
10511 unsigned MinRepeats) const {
10512 unsigned SequenceSize = 0;
10513 for (auto &MI : RepeatedSequenceLocs[0])
10514 SequenceSize += getInstSizeInBytes(MI);
10515
10516 unsigned NumBytesToCreateFrame = 0;
10517
10518 // Avoid splitting ADRP ADD/LDR pair into outlined functions.
10519 // These instructions are fused together by the scheduler.
10520 // Any candidate where ADRP is the last instruction should be rejected
10521 // as that will lead to splitting ADRP pair.
10522 MachineInstr &LastMI = RepeatedSequenceLocs[0].back();
10523 MachineInstr &FirstMI = RepeatedSequenceLocs[0].front();
10524 if (LastMI.getOpcode() == AArch64::ADRP &&
10525 (LastMI.getOperand(1).getTargetFlags() & AArch64II::MO_PAGE) != 0 &&
10526 (LastMI.getOperand(1).getTargetFlags() & AArch64II::MO_GOT) != 0) {
10527 return std::nullopt;
10528 }
10529
10530 // Similarly any candidate where the first instruction is ADD/LDR with a
10531 // page offset should be rejected to avoid ADRP splitting.
10532 if ((FirstMI.getOpcode() == AArch64::ADDXri ||
10533 FirstMI.getOpcode() == AArch64::LDRXui) &&
10534 (FirstMI.getOperand(2).getTargetFlags() & AArch64II::MO_PAGEOFF) != 0 &&
10535 (FirstMI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT) != 0) {
10536 return std::nullopt;
10537 }
10538
10539 // We only allow outlining for functions having exactly matching return
10540 // address signing attributes, i.e., all share the same value for the
10541 // attribute "sign-return-address" and all share the same type of key they
10542 // are signed with.
10543 // Additionally we require all functions to simultaneously either support
10544 // v8.3a features or not. Otherwise an outlined function could get signed
10545 // using dedicated v8.3 instructions and a call from a function that doesn't
10546 // support v8.3 instructions would therefore be invalid.
10547 if (std::adjacent_find(
10548 RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(),
10549 [](const outliner::Candidate &a, const outliner::Candidate &b) {
10550 // Return true if a and b are non-equal w.r.t. return address
10551 // signing or support of v8.3a features
10552 if (outliningCandidatesSigningScopeConsensus(a, b) &&
10553 outliningCandidatesSigningKeyConsensus(a, b) &&
10554 outliningCandidatesV8_3OpsConsensus(a, b)) {
10555 return false;
10556 }
10557 return true;
10558 }) != RepeatedSequenceLocs.end()) {
10559 return std::nullopt;
10560 }
10561
10562 // Since at this point all candidates agree on their return address signing
10563 // picking just one is fine. If the candidate functions potentially sign their
10564 // return addresses, the outlined function should do the same. Note that in
10565 // the case of "sign-return-address"="non-leaf" this is an assumption: It is
10566 // not certainly true that the outlined function will have to sign its return
10567 // address but this decision is made later, when the decision to outline
10568 // has already been made.
10569 // The same holds for the number of additional instructions we need: On
10570 // v8.3a RET can be replaced by RETAA/RETAB and no AUT instruction is
10571 // necessary. However, at this point we don't know if the outlined function
10572 // will have a RET instruction so we assume the worst.
10573 const TargetRegisterInfo &TRI = getRegisterInfo();
10574 // Performing a tail call may require extra checks when PAuth is enabled.
10575 // If PAuth is disabled, set it to zero for uniformity.
10576 unsigned NumBytesToCheckLRInTCEpilogue = 0;
10577 const auto RASignCondition = RepeatedSequenceLocs[0]
10578 .getMF()
10579 ->getInfo<AArch64FunctionInfo>()
10580 ->getSignReturnAddressCondition();
10581 if (RASignCondition != SignReturnAddress::None) {
10582 // One PAC and one AUT instructions
10583 NumBytesToCreateFrame += 8;
10584
10585 // PAuth is enabled - set extra tail call cost, if any.
10586 auto LRCheckMethod = Subtarget.getAuthenticatedLRCheckMethod(
10587 *RepeatedSequenceLocs[0].getMF());
10588 NumBytesToCheckLRInTCEpilogue =
10590 // Checking the authenticated LR value may significantly impact
10591 // SequenceSize, so account for it for more precise results.
10592 if (isTailCallReturnInst(RepeatedSequenceLocs[0].back()))
10593 SequenceSize += NumBytesToCheckLRInTCEpilogue;
10594
10595 // We have to check if sp modifying instructions would get outlined.
10596 // If so we only allow outlining if sp is unchanged overall, so matching
10597 // sub and add instructions are okay to outline, all other sp modifications
10598 // are not
10599 auto hasIllegalSPModification = [&TRI](outliner::Candidate &C) {
10600 int SPValue = 0;
10601 for (auto &MI : C) {
10602 if (MI.modifiesRegister(AArch64::SP, &TRI)) {
10603 switch (MI.getOpcode()) {
10604 case AArch64::ADDXri:
10605 case AArch64::ADDWri:
10606 assert(MI.getNumOperands() == 4 && "Wrong number of operands");
10607 assert(MI.getOperand(2).isImm() &&
10608 "Expected operand to be immediate");
10609 assert(MI.getOperand(1).isReg() &&
10610 "Expected operand to be a register");
10611 // Check if the add just increments sp. If so, we search for
10612 // matching sub instructions that decrement sp. If not, the
10613 // modification is illegal
10614 if (MI.getOperand(1).getReg() == AArch64::SP)
10615 SPValue += MI.getOperand(2).getImm();
10616 else
10617 return true;
10618 break;
10619 case AArch64::SUBXri:
10620 case AArch64::SUBWri:
10621 assert(MI.getNumOperands() == 4 && "Wrong number of operands");
10622 assert(MI.getOperand(2).isImm() &&
10623 "Expected operand to be immediate");
10624 assert(MI.getOperand(1).isReg() &&
10625 "Expected operand to be a register");
10626 // Check if the sub just decrements sp. If so, we search for
10627 // matching add instructions that increment sp. If not, the
10628 // modification is illegal
10629 if (MI.getOperand(1).getReg() == AArch64::SP)
10630 SPValue -= MI.getOperand(2).getImm();
10631 else
10632 return true;
10633 break;
10634 default:
10635 return true;
10636 }
10637 }
10638 }
10639 if (SPValue)
10640 return true;
10641 return false;
10642 };
10643 // Remove candidates with illegal stack modifying instructions
10644 llvm::erase_if(RepeatedSequenceLocs, hasIllegalSPModification);
10645
10646 // If the sequence doesn't have enough candidates left, then we're done.
10647 if (RepeatedSequenceLocs.size() < MinRepeats)
10648 return std::nullopt;
10649 }
10650
10651 // Properties about candidate MBBs that hold for all of them.
10652 unsigned FlagsSetInAll = 0xF;
10653
10654 // Compute liveness information for each candidate, and set FlagsSetInAll.
10655 for (outliner::Candidate &C : RepeatedSequenceLocs)
10656 FlagsSetInAll &= C.Flags;
10657
10658 unsigned LastInstrOpcode = RepeatedSequenceLocs[0].back().getOpcode();
10659
10660 // Helper lambda which sets call information for every candidate.
10661 auto SetCandidateCallInfo =
10662 [&RepeatedSequenceLocs](unsigned CallID, unsigned NumBytesForCall) {
10663 for (outliner::Candidate &C : RepeatedSequenceLocs)
10664 C.setCallInfo(CallID, NumBytesForCall);
10665 };
10666
10667 unsigned FrameID = MachineOutlinerDefault;
10668 NumBytesToCreateFrame += 4;
10669
10670 bool HasBTI = any_of(RepeatedSequenceLocs, [](outliner::Candidate &C) {
10671 return C.getMF()->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement();
10672 });
10673
10674 // We check to see if CFI Instructions are present, and if they are
10675 // we find the number of CFI Instructions in the candidates.
10676 unsigned CFICount = 0;
10677 for (auto &I : RepeatedSequenceLocs[0]) {
10678 if (I.isCFIInstruction())
10679 CFICount++;
10680 }
10681
10682 // We compare the number of found CFI Instructions to the number of CFI
10683 // instructions in the parent function for each candidate. We must check this
10684 // since if we outline one of the CFI instructions in a function, we have to
10685 // outline them all for correctness. If we do not, the address offsets will be
10686 // incorrect between the two sections of the program.
10687 for (outliner::Candidate &C : RepeatedSequenceLocs) {
10688 std::vector<MCCFIInstruction> CFIInstructions =
10689 C.getMF()->getFrameInstructions();
10690
10691 if (CFICount > 0 && CFICount != CFIInstructions.size())
10692 return std::nullopt;
10693 }
10694
10695 // Returns true if an instructions is safe to fix up, false otherwise.
10696 auto IsSafeToFixup = [this, &TRI](MachineInstr &MI) {
10697 if (MI.isCall())
10698 return true;
10699
10700 if (!MI.modifiesRegister(AArch64::SP, &TRI) &&
10701 !MI.readsRegister(AArch64::SP, &TRI))
10702 return true;
10703
10704 // Any modification of SP will break our code to save/restore LR.
10705 // FIXME: We could handle some instructions which add a constant
10706 // offset to SP, with a bit more work.
10707 if (MI.modifiesRegister(AArch64::SP, &TRI))
10708 return false;
10709
10710 // At this point, we have a stack instruction that we might need to
10711 // fix up. We'll handle it if it's a load or store.
10712 if (MI.mayLoadOrStore()) {
10713 const MachineOperand *Base; // Filled with the base operand of MI.
10714 int64_t Offset; // Filled with the offset of MI.
10715 bool OffsetIsScalable;
10716
10717 // Does it allow us to offset the base operand and is the base the
10718 // register SP?
10719 if (!getMemOperandWithOffset(MI, Base, Offset, OffsetIsScalable, &TRI) ||
10720 !Base->isReg() || Base->getReg() != AArch64::SP)
10721 return false;
10722
10723 // Fixe-up code below assumes bytes.
10724 if (OffsetIsScalable)
10725 return false;
10726
10727 // Find the minimum/maximum offset for this instruction and check
10728 // if fixing it up would be in range.
10729 int64_t MinOffset,
10730 MaxOffset; // Unscaled offsets for the instruction.
10731 // The scale to multiply the offsets by.
10732 TypeSize Scale(0U, false), DummyWidth(0U, false);
10733 getMemOpInfo(MI.getOpcode(), Scale, DummyWidth, MinOffset, MaxOffset);
10734
10735 Offset += 16; // Update the offset to what it would be if we outlined.
10736 if (Offset < MinOffset * (int64_t)Scale.getFixedValue() ||
10737 Offset > MaxOffset * (int64_t)Scale.getFixedValue())
10738 return false;
10739
10740 // It's in range, so we can outline it.
10741 return true;
10742 }
10743
10744 // FIXME: Add handling for instructions like "add x0, sp, #8".
10745
10746 // We can't fix it up, so don't outline it.
10747 return false;
10748 };
10749
10750 // True if it's possible to fix up each stack instruction in this sequence.
10751 // Important for frames/call variants that modify the stack.
10752 bool AllStackInstrsSafe =
10753 llvm::all_of(RepeatedSequenceLocs[0], IsSafeToFixup);
10754
10755 // If the last instruction in any candidate is a terminator, then we should
10756 // tail call all of the candidates.
10757 if (RepeatedSequenceLocs[0].back().isTerminator()) {
10758 FrameID = MachineOutlinerTailCall;
10759 NumBytesToCreateFrame = 0;
10760 unsigned NumBytesForCall = 4 + NumBytesToCheckLRInTCEpilogue;
10761 SetCandidateCallInfo(MachineOutlinerTailCall, NumBytesForCall);
10762 }
10763
10764 else if (LastInstrOpcode == AArch64::BL ||
10765 ((LastInstrOpcode == AArch64::BLR ||
10766 LastInstrOpcode == AArch64::BLRNoIP) &&
10767 !HasBTI)) {
10768 // FIXME: Do we need to check if the code after this uses the value of LR?
10769 FrameID = MachineOutlinerThunk;
10770 NumBytesToCreateFrame = NumBytesToCheckLRInTCEpilogue;
10771 SetCandidateCallInfo(MachineOutlinerThunk, 4);
10772 }
10773
10774 else {
10775 // We need to decide how to emit calls + frames. We can always emit the same
10776 // frame if we don't need to save to the stack. If we have to save to the
10777 // stack, then we need a different frame.
10778 unsigned NumBytesNoStackCalls = 0;
10779 std::vector<outliner::Candidate> CandidatesWithoutStackFixups;
10780
10781 // Check if we have to save LR.
10782 for (outliner::Candidate &C : RepeatedSequenceLocs) {
10783 bool LRAvailable =
10785 ? C.isAvailableAcrossAndOutOfSeq(AArch64::LR, TRI)
10786 : true;
10787 // If we have a noreturn caller, then we're going to be conservative and
10788 // say that we have to save LR. If we don't have a ret at the end of the
10789 // block, then we can't reason about liveness accurately.
10790 //
10791 // FIXME: We can probably do better than always disabling this in
10792 // noreturn functions by fixing up the liveness info.
10793 bool IsNoReturn =
10794 C.getMF()->getFunction().hasFnAttribute(Attribute::NoReturn);
10795
10796 // Is LR available? If so, we don't need a save.
10797 if (LRAvailable && !IsNoReturn) {
10798 NumBytesNoStackCalls += 4;
10799 C.setCallInfo(MachineOutlinerNoLRSave, 4);
10800 CandidatesWithoutStackFixups.push_back(C);
10801 }
10802
10803 // Is an unused register available? If so, we won't modify the stack, so
10804 // we can outline with the same frame type as those that don't save LR.
10805 else if (findRegisterToSaveLRTo(C)) {
10806 NumBytesNoStackCalls += 12;
10807 C.setCallInfo(MachineOutlinerRegSave, 12);
10808 CandidatesWithoutStackFixups.push_back(C);
10809 }
10810
10811 // Is SP used in the sequence at all? If not, we don't have to modify
10812 // the stack, so we are guaranteed to get the same frame.
10813 else if (C.isAvailableInsideSeq(AArch64::SP, TRI)) {
10814 NumBytesNoStackCalls += 12;
10815 C.setCallInfo(MachineOutlinerDefault, 12);
10816 CandidatesWithoutStackFixups.push_back(C);
10817 }
10818
10819 // If we outline this, we need to modify the stack. Pretend we don't
10820 // outline this by saving all of its bytes.
10821 else {
10822 NumBytesNoStackCalls += SequenceSize;
10823 }
10824 }
10825
10826 // If there are no places where we have to save LR, then note that we
10827 // don't have to update the stack. Otherwise, give every candidate the
10828 // default call type, as long as it's safe to do so.
10829 if (!AllStackInstrsSafe ||
10830 NumBytesNoStackCalls <= RepeatedSequenceLocs.size() * 12) {
10831 RepeatedSequenceLocs = CandidatesWithoutStackFixups;
10832 FrameID = MachineOutlinerNoLRSave;
10833 if (RepeatedSequenceLocs.size() < MinRepeats)
10834 return std::nullopt;
10835 } else {
10836 SetCandidateCallInfo(MachineOutlinerDefault, 12);
10837
10838 // Bugzilla ID: 46767
10839 // TODO: Check if fixing up the stack more than once is safe so we can
10840 // outline these.
10841 //
10842 // An outline resulting in a caller that requires stack fixups at the
10843 // callsite to a callee that also requires stack fixups can happen when
10844 // there are no available registers at the candidate callsite for a
10845 // candidate that itself also has calls.
10846 //
10847 // In other words if function_containing_sequence in the following pseudo
10848 // assembly requires that we save LR at the point of the call, but there
10849 // are no available registers: in this case we save using SP and as a
10850 // result the SP offsets requires stack fixups by multiples of 16.
10851 //
10852 // function_containing_sequence:
10853 // ...
10854 // save LR to SP <- Requires stack instr fixups in OUTLINED_FUNCTION_N
10855 // call OUTLINED_FUNCTION_N
10856 // restore LR from SP
10857 // ...
10858 //
10859 // OUTLINED_FUNCTION_N:
10860 // save LR to SP <- Requires stack instr fixups in OUTLINED_FUNCTION_N
10861 // ...
10862 // bl foo
10863 // restore LR from SP
10864 // ret
10865 //
10866 // Because the code to handle more than one stack fixup does not
10867 // currently have the proper checks for legality, these cases will assert
10868 // in the AArch64 MachineOutliner. This is because the code to do this
10869 // needs more hardening, testing, better checks that generated code is
10870 // legal, etc and because it is only verified to handle a single pass of
10871 // stack fixup.
10872 //
10873 // The assert happens in AArch64InstrInfo::buildOutlinedFrame to catch
10874 // these cases until they are known to be handled. Bugzilla 46767 is
10875 // referenced in comments at the assert site.
10876 //
10877 // To avoid asserting (or generating non-legal code on noassert builds)
10878 // we remove all candidates which would need more than one stack fixup by
10879 // pruning the cases where the candidate has calls while also having no
10880 // available LR and having no available general purpose registers to copy
10881 // LR to (ie one extra stack save/restore).
10882 //
10883 if (FlagsSetInAll & MachineOutlinerMBBFlags::HasCalls) {
10884 erase_if(RepeatedSequenceLocs, [this, &TRI](outliner::Candidate &C) {
10885 auto IsCall = [](const MachineInstr &MI) { return MI.isCall(); };
10886 return (llvm::any_of(C, IsCall)) &&
10887 (!C.isAvailableAcrossAndOutOfSeq(AArch64::LR, TRI) ||
10888 !findRegisterToSaveLRTo(C));
10889 });
10890 }
10891 }
10892
10893 // If we dropped all of the candidates, bail out here.
10894 if (RepeatedSequenceLocs.size() < MinRepeats)
10895 return std::nullopt;
10896 }
10897
10898 // Does every candidate's MBB contain a call? If so, then we might have a call
10899 // in the range.
10900 if (FlagsSetInAll & MachineOutlinerMBBFlags::HasCalls) {
10901 // Check if the range contains a call. These require a save + restore of the
10902 // link register.
10903 outliner::Candidate &FirstCand = RepeatedSequenceLocs[0];
10904 bool ModStackToSaveLR = false;
10905 if (any_of(drop_end(FirstCand),
10906 [](const MachineInstr &MI) { return MI.isCall(); }))
10907 ModStackToSaveLR = true;
10908
10909 // Handle the last instruction separately. If this is a tail call, then the
10910 // last instruction is a call. We don't want to save + restore in this case.
10911 // However, it could be possible that the last instruction is a call without
10912 // it being valid to tail call this sequence. We should consider this as
10913 // well.
10914 else if (FrameID != MachineOutlinerThunk &&
10915 FrameID != MachineOutlinerTailCall && FirstCand.back().isCall())
10916 ModStackToSaveLR = true;
10917
10918 if (ModStackToSaveLR) {
10919 // We can't fix up the stack. Bail out.
10920 if (!AllStackInstrsSafe)
10921 return std::nullopt;
10922
10923 // Save + restore LR.
10924 NumBytesToCreateFrame += 8;
10925
10926 // Add the extra mov if we will save a frame record instead of just LR.
10928 RepeatedSequenceLocs, TRI))
10929 NumBytesToCreateFrame += 4;
10930 }
10931 }
10932
10933 // If we have CFI instructions, we can only outline if the outlined section
10934 // can be a tail call
10935 if (FrameID != MachineOutlinerTailCall && CFICount > 0)
10936 return std::nullopt;
10937
10938 return std::make_unique<outliner::OutlinedFunction>(
10939 RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID);
10940}
10941
10942void AArch64InstrInfo::mergeOutliningCandidateAttributes(
10943 Function &F, std::vector<outliner::Candidate> &Candidates) const {
10944 // If a bunch of candidates reach this point they must agree on their return
10945 // address signing. It is therefore enough to just consider the signing
10946 // behaviour of one of them
10947 const auto &CFn = Candidates.front().getMF()->getFunction();
10948
10949 if (CFn.hasFnAttribute("ptrauth-returns"))
10950 F.addFnAttr(CFn.getFnAttribute("ptrauth-returns"));
10951 if (CFn.hasFnAttribute("ptrauth-auth-traps"))
10952 F.addFnAttr(CFn.getFnAttribute("ptrauth-auth-traps"));
10953 // Since all candidates belong to the same module, just copy the
10954 // function-level attributes of an arbitrary function.
10955 if (CFn.hasFnAttribute("sign-return-address"))
10956 F.addFnAttr(CFn.getFnAttribute("sign-return-address"));
10957 if (CFn.hasFnAttribute("sign-return-address-key"))
10958 F.addFnAttr(CFn.getFnAttribute("sign-return-address-key"));
10959
10960 AArch64GenInstrInfo::mergeOutliningCandidateAttributes(F, Candidates);
10961}
10962
10963bool AArch64InstrInfo::isFunctionSafeToOutlineFrom(
10964 MachineFunction &MF, bool OutlineFromLinkOnceODRs) const {
10965 const Function &F = MF.getFunction();
10966
10967 // Can F be deduplicated by the linker? If it can, don't outline from it.
10968 if (!OutlineFromLinkOnceODRs && F.hasLinkOnceODRLinkage())
10969 return false;
10970
10971 // Don't outline from functions with section markings; the program could
10972 // expect that all the code is in the named section.
10973 // FIXME: Allow outlining from multiple functions with the same section
10974 // marking.
10975 if (F.hasSection())
10976 return false;
10977
10978 // Outlining from functions with redzones is unsafe since the outliner may
10979 // modify the stack. Check if hasRedZone is true or unknown; if yes, don't
10980 // outline from it.
10981 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
10982 if (!AFI || AFI->hasRedZone().value_or(true))
10983 return false;
10984
10985 // FIXME: Determine whether it is safe to outline from functions which contain
10986 // streaming-mode changes. We may need to ensure any smstart/smstop pairs are
10987 // outlined together and ensure it is safe to outline with async unwind info,
10988 // required for saving & restoring VG around calls.
10989 if (AFI->hasStreamingModeChanges())
10990 return false;
10991
10992 // FIXME: Teach the outliner to generate/handle Windows unwind info.
10994 return false;
10995
10996 // It's safe to outline from MF.
10997 return true;
10998}
10999
11001AArch64InstrInfo::getOutlinableRanges(MachineBasicBlock &MBB,
11002 unsigned &Flags) const {
11004 "Must track liveness!");
11006 std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
11007 Ranges;
11008 // According to the AArch64 Procedure Call Standard, the following are
11009 // undefined on entry/exit from a function call:
11010 //
11011 // * Registers x16, x17, (and thus w16, w17)
11012 // * Condition codes (and thus the NZCV register)
11013 //
11014 // If any of these registers are used inside or live across an outlined
11015 // function, then they may be modified later, either by the compiler or
11016 // some other tool (like the linker).
11017 //
11018 // To avoid outlining in these situations, partition each block into ranges
11019 // where these registers are dead. We will only outline from those ranges.
11020 LiveRegUnits LRU(getRegisterInfo());
11021 auto AreAllUnsafeRegsDead = [&LRU]() {
11022 return LRU.available(AArch64::W16) && LRU.available(AArch64::W17) &&
11023 LRU.available(AArch64::NZCV);
11024 };
11025
11026 // We need to know if LR is live across an outlining boundary later on in
11027 // order to decide how we'll create the outlined call, frame, etc.
11028 //
11029 // It's pretty expensive to check this for *every candidate* within a block.
11030 // That's some potentially n^2 behaviour, since in the worst case, we'd need
11031 // to compute liveness from the end of the block for O(n) candidates within
11032 // the block.
11033 //
11034 // So, to improve the average case, let's keep track of liveness from the end
11035 // of the block to the beginning of *every outlinable range*. If we know that
11036 // LR is available in every range we could outline from, then we know that
11037 // we don't need to check liveness for any candidate within that range.
11038 bool LRAvailableEverywhere = true;
11039 // Compute liveness bottom-up.
11040 LRU.addLiveOuts(MBB);
11041 // Update flags that require info about the entire MBB.
11042 auto UpdateWholeMBBFlags = [&Flags](const MachineInstr &MI) {
11043 if (MI.isCall() && !MI.isTerminator())
11045 };
11046 // Range: [RangeBegin, RangeEnd)
11047 MachineBasicBlock::instr_iterator RangeBegin, RangeEnd;
11048 unsigned RangeLen;
11049 auto CreateNewRangeStartingAt =
11050 [&RangeBegin, &RangeEnd,
11051 &RangeLen](MachineBasicBlock::instr_iterator NewBegin) {
11052 RangeBegin = NewBegin;
11053 RangeEnd = std::next(RangeBegin);
11054 RangeLen = 0;
11055 };
11056 auto SaveRangeIfNonEmpty = [&RangeLen, &Ranges, &RangeBegin, &RangeEnd]() {
11057 // At least one unsafe register is not dead. We do not want to outline at
11058 // this point. If it is long enough to outline from and does not cross a
11059 // bundle boundary, save the range [RangeBegin, RangeEnd).
11060 if (RangeLen <= 1)
11061 return;
11062 if (!RangeBegin.isEnd() && RangeBegin->isBundledWithPred())
11063 return;
11064 if (!RangeEnd.isEnd() && RangeEnd->isBundledWithPred())
11065 return;
11066 Ranges.emplace_back(RangeBegin, RangeEnd);
11067 };
11068 // Find the first point where all unsafe registers are dead.
11069 // FIND: <safe instr> <-- end of first potential range
11070 // SKIP: <unsafe def>
11071 // SKIP: ... everything between ...
11072 // SKIP: <unsafe use>
11073 auto FirstPossibleEndPt = MBB.instr_rbegin();
11074 for (; FirstPossibleEndPt != MBB.instr_rend(); ++FirstPossibleEndPt) {
11075 if (!FirstPossibleEndPt->isDebugInstr())
11076 LRU.stepBackward(*FirstPossibleEndPt);
11077 // Update flags that impact how we outline across the entire block,
11078 // regardless of safety.
11079 UpdateWholeMBBFlags(*FirstPossibleEndPt);
11080 if (AreAllUnsafeRegsDead())
11081 break;
11082 }
11083 // If we exhausted the entire block, we have no safe ranges to outline.
11084 if (FirstPossibleEndPt == MBB.instr_rend())
11085 return Ranges;
11086 // Current range.
11087 CreateNewRangeStartingAt(FirstPossibleEndPt->getIterator());
11088 // StartPt points to the first place where all unsafe registers
11089 // are dead (if there is any such point). Begin partitioning the MBB into
11090 // ranges.
11091 for (auto &MI : make_range(FirstPossibleEndPt, MBB.instr_rend())) {
11092 if (!MI.isDebugInstr())
11093 LRU.stepBackward(MI);
11094 UpdateWholeMBBFlags(MI);
11095 if (!AreAllUnsafeRegsDead()) {
11096 SaveRangeIfNonEmpty();
11097 CreateNewRangeStartingAt(MI.getIterator());
11098 continue;
11099 }
11100 LRAvailableEverywhere &= LRU.available(AArch64::LR);
11101 // RangeBegin may point at a debug instruction because the mapper ignores
11102 // debug instructions wherever they appear. Only count non-debug
11103 // instructions so debug info cannot make a short range outlinable.
11104 RangeBegin = MI.getIterator();
11105 if (!MI.isDebugInstr())
11106 ++RangeLen;
11107 }
11108 // Above loop misses the last (or only) range. If we are still safe, then
11109 // let's save the range.
11110 if (AreAllUnsafeRegsDead())
11111 SaveRangeIfNonEmpty();
11112 if (Ranges.empty())
11113 return Ranges;
11114 // We found the ranges bottom-up. Mapping expects the top-down. Reverse
11115 // the order.
11116 std::reverse(Ranges.begin(), Ranges.end());
11117 // If there is at least one outlinable range where LR is unavailable
11118 // somewhere, remember that.
11119 if (!LRAvailableEverywhere)
11121 return Ranges;
11122}
11123
11125AArch64InstrInfo::getOutliningTypeImpl(const MachineModuleInfo &MMI,
11127 unsigned Flags) const {
11128 MachineInstr &MI = *MIT;
11129
11130 // Don't outline anything used for return address signing. The outlined
11131 // function will get signed later if needed
11132 switch (MI.getOpcode()) {
11133 case AArch64::PACM:
11134 case AArch64::PACIASP:
11135 case AArch64::PACIBSP:
11136 case AArch64::PACIASPPC:
11137 case AArch64::PACIBSPPC:
11138 case AArch64::AUTIASP:
11139 case AArch64::AUTIBSP:
11140 case AArch64::AUTIASPPCi:
11141 case AArch64::AUTIASPPCr:
11142 case AArch64::AUTIBSPPCi:
11143 case AArch64::AUTIBSPPCr:
11144 case AArch64::RETAA:
11145 case AArch64::RETAB:
11146 case AArch64::RETAASPPCi:
11147 case AArch64::RETAASPPCr:
11148 case AArch64::RETABSPPCi:
11149 case AArch64::RETABSPPCr:
11150 case AArch64::EMITBKEY:
11151 case AArch64::PAUTH_PROLOGUE:
11152 case AArch64::PAUTH_EPILOGUE:
11154 }
11155
11156 // We can only outline these if we will tail call the outlined function, or
11157 // fix up the CFI offsets. Currently, CFI instructions are outlined only if
11158 // in a tail call.
11159 //
11160 // FIXME: If the proper fixups for the offset are implemented, this should be
11161 // possible.
11162 if (MI.isCFIInstruction())
11164
11165 // Is this a terminator for a basic block?
11166 if (MI.isTerminator())
11167 // TargetInstrInfo::getOutliningType has already filtered out anything
11168 // that would break this, so we can allow it here.
11170
11171 // Make sure none of the operands are un-outlinable.
11172 for (const MachineOperand &MOP : MI.operands()) {
11173 // A check preventing CFI indices was here before, but only CFI
11174 // instructions should have those.
11175 assert(!MOP.isCFIIndex());
11176
11177 // If it uses LR or W30 explicitly, then don't touch it.
11178 if (MOP.isReg() && !MOP.isImplicit() &&
11179 (MOP.getReg() == AArch64::LR || MOP.getReg() == AArch64::W30))
11181 }
11182
11183 // Special cases for instructions that can always be outlined, but will fail
11184 // the later tests. e.g, ADRPs, which are PC-relative use LR, but can always
11185 // be outlined because they don't require a *specific* value to be in LR.
11186 if (MI.getOpcode() == AArch64::ADRP)
11188
11189 // If MI is a call we might be able to outline it. We don't want to outline
11190 // any calls that rely on the position of items on the stack. When we outline
11191 // something containing a call, we have to emit a save and restore of LR in
11192 // the outlined function. Currently, this always happens by saving LR to the
11193 // stack. Thus, if we outline, say, half the parameters for a function call
11194 // plus the call, then we'll break the callee's expectations for the layout
11195 // of the stack.
11196 //
11197 // FIXME: Allow calls to functions which construct a stack frame, as long
11198 // as they don't access arguments on the stack.
11199 // FIXME: Figure out some way to analyze functions defined in other modules.
11200 // We should be able to compute the memory usage based on the IR calling
11201 // convention, even if we can't see the definition.
11202 if (MI.isCall()) {
11203 // Get the function associated with the call. Look at each operand and find
11204 // the one that represents the callee and get its name.
11205 const Function *Callee = nullptr;
11206 for (const MachineOperand &MOP : MI.operands()) {
11207 if (MOP.isGlobal()) {
11208 Callee = dyn_cast<Function>(MOP.getGlobal());
11209 break;
11210 }
11211 }
11212
11213 // Never outline calls to mcount. There isn't any rule that would require
11214 // this, but the Linux kernel's "ftrace" feature depends on it.
11215 if (Callee && Callee->getName() == "\01_mcount")
11217
11218 // If we don't know anything about the callee, assume it depends on the
11219 // stack layout of the caller. In that case, it's only legal to outline
11220 // as a tail-call. Explicitly list the call instructions we know about so we
11221 // don't get unexpected results with call pseudo-instructions.
11222 auto UnknownCallOutlineType = outliner::InstrType::Illegal;
11223 if (MI.getOpcode() == AArch64::BLR ||
11224 MI.getOpcode() == AArch64::BLRNoIP || MI.getOpcode() == AArch64::BL)
11225 UnknownCallOutlineType = outliner::InstrType::LegalTerminator;
11226
11227 if (!Callee)
11228 return UnknownCallOutlineType;
11229
11230 // We have a function we have information about. Check it if it's something
11231 // can safely outline.
11232 MachineFunction *CalleeMF = MMI.getMachineFunction(*Callee);
11233
11234 // We don't know what's going on with the callee at all. Don't touch it.
11235 if (!CalleeMF)
11236 return UnknownCallOutlineType;
11237
11238 // Check if we know anything about the callee saves on the function. If we
11239 // don't, then don't touch it, since that implies that we haven't
11240 // computed anything about its stack frame yet.
11241 MachineFrameInfo &MFI = CalleeMF->getFrameInfo();
11242 if (!MFI.isCalleeSavedInfoValid() || MFI.getStackSize() > 0 ||
11243 MFI.getNumObjects() > 0)
11244 return UnknownCallOutlineType;
11245
11246 // At this point, we can say that CalleeMF ought to not pass anything on the
11247 // stack. Therefore, we can outline it.
11249 }
11250
11251 // Don't touch the link register or W30.
11252 if (MI.readsRegister(AArch64::W30, &getRegisterInfo()) ||
11253 MI.modifiesRegister(AArch64::W30, &getRegisterInfo()))
11255
11256 // Don't outline BTI instructions, because that will prevent the outlining
11257 // site from being indirectly callable.
11258 if (hasBTISemantics(MI))
11260
11262}
11263
11264void AArch64InstrInfo::fixupPostOutline(MachineBasicBlock &MBB) const {
11265 for (MachineInstr &MI : MBB) {
11266 const MachineOperand *Base;
11267 TypeSize Width(0, false);
11268 int64_t Offset;
11269 bool OffsetIsScalable;
11270
11271 // Is this a load or store with an immediate offset with SP as the base?
11272 if (!MI.mayLoadOrStore() ||
11273 !getMemOperandWithOffsetWidth(MI, Base, Offset, OffsetIsScalable, Width,
11274 &RI) ||
11275 (Base->isReg() && Base->getReg() != AArch64::SP))
11276 continue;
11277
11278 // It is, so we have to fix it up.
11279 TypeSize Scale(0U, false);
11280 int64_t Dummy1, Dummy2;
11281
11282 MachineOperand &StackOffsetOperand = getMemOpBaseRegImmOfsOffsetOperand(MI);
11283 assert(StackOffsetOperand.isImm() && "Stack offset wasn't immediate!");
11284 getMemOpInfo(MI.getOpcode(), Scale, Width, Dummy1, Dummy2);
11285 assert(Scale != 0 && "Unexpected opcode!");
11286 assert(!OffsetIsScalable && "Expected offset to be a byte offset");
11287
11288 // We've pushed the return address to the stack, so add 16 to the offset.
11289 // This is safe, since we already checked if it would overflow when we
11290 // checked if this instruction was legal to outline.
11291 int64_t NewImm = (Offset + 16) / (int64_t)Scale.getFixedValue();
11292 StackOffsetOperand.setImm(NewImm);
11293 }
11294}
11295
11297 const AArch64InstrInfo *TII,
11298 bool ShouldSignReturnAddr) {
11299 if (!ShouldSignReturnAddr)
11300 return;
11301
11302 BuildMI(MBB, MBB.begin(), DebugLoc(), TII->get(AArch64::PAUTH_PROLOGUE))
11304 TII->createPauthEpilogueInstr(MBB, DebugLoc());
11305}
11306
11307void AArch64InstrInfo::buildOutlinedFrame(
11309 const outliner::OutlinedFunction &OF) const {
11310
11311 AArch64FunctionInfo *FI = MF.getInfo<AArch64FunctionInfo>();
11312
11313 if (OF.FrameConstructionID == MachineOutlinerTailCall)
11314 FI->setOutliningStyle("Tail Call");
11315 else if (OF.FrameConstructionID == MachineOutlinerThunk) {
11316 // For thunk outlining, rewrite the last instruction from a call to a
11317 // tail-call.
11318 MachineInstr *Call = &*--MBB.instr_end();
11319 unsigned TailOpcode;
11320 if (Call->getOpcode() == AArch64::BL) {
11321 TailOpcode = AArch64::TCRETURNdi;
11322 } else {
11323 assert(Call->getOpcode() == AArch64::BLR ||
11324 Call->getOpcode() == AArch64::BLRNoIP);
11325 TailOpcode = AArch64::TCRETURNriALL;
11326 }
11327 MachineInstr *TC = BuildMI(MF, DebugLoc(), get(TailOpcode))
11328 .add(Call->getOperand(0))
11329 .addImm(0);
11330 MBB.insert(MBB.end(), TC);
11332
11333 FI->setOutliningStyle("Thunk");
11334 }
11335
11336 bool IsLeafFunction = true;
11337
11338 // Is there a call in the outlined range?
11339 auto IsNonTailCall = [](const MachineInstr &MI) {
11340 return MI.isCall() && !MI.isReturn();
11341 };
11342
11343 if (llvm::any_of(MBB.instrs(), IsNonTailCall)) {
11344 // Fix up the instructions in the range, since we're going to modify the
11345 // stack.
11346
11347 // Bugzilla ID: 46767
11348 // TODO: Check if fixing up twice is safe so we can outline these.
11349 assert(OF.FrameConstructionID != MachineOutlinerDefault &&
11350 "Can only fix up stack references once");
11351 fixupPostOutline(MBB);
11352
11353 IsLeafFunction = false;
11354
11355 // LR has to be a live in so that we can save it.
11356 if (!MBB.isLiveIn(AArch64::LR))
11357 MBB.addLiveIn(AArch64::LR);
11358
11361
11362 if (OF.FrameConstructionID == MachineOutlinerTailCall ||
11363 OF.FrameConstructionID == MachineOutlinerThunk)
11364 Et = std::prev(MBB.end());
11365
11366 // There is a call in the range, so we must save LR. Save it as part of a
11367 // frame record when that gives us a smaller compact unwind encoding.
11369 // FP is saved here, so it must be live-in.
11370 if (!MBB.isLiveIn(AArch64::FP))
11371 MBB.addLiveIn(AArch64::FP);
11372
11373 // stp x29, x30, [sp, #-16]! (the pre-index imm is scaled by 8: -2 * 8)
11374 MachineInstr *STPXpre = BuildMI(MF, DebugLoc(), get(AArch64::STPXpre))
11375 .addReg(AArch64::SP, RegState::Define)
11376 .addReg(AArch64::FP)
11377 .addReg(AArch64::LR)
11378 .addReg(AArch64::SP)
11379 .addImm(-2);
11380 It = MBB.insert(It, STPXpre);
11381
11382 // mov x29, sp (add x29, sp, #0), so x29 points at the frame record.
11383 MachineInstr *SetFP = BuildMI(MF, DebugLoc(), get(AArch64::ADDXri))
11384 .addReg(AArch64::FP, RegState::Define)
11385 .addReg(AArch64::SP)
11386 .addImm(0)
11387 .addImm(0);
11388 MBB.insertAfter(It, SetFP);
11389
11390 // Describe the frame record with FP as the CFA. The encoder needs all
11391 // three to pick FRAME. No need to check for unwind info here: we only
11392 // get here if the function has it.
11393 CFIInstBuilder CFIBuilder(MBB, std::next(SetFP->getIterator()),
11395 CFIBuilder.buildDefCFA(AArch64::FP, 16);
11396 CFIBuilder.buildOffset(AArch64::LR, -8);
11397 CFIBuilder.buildOffset(AArch64::FP, -16);
11398
11399 // ldp x29, x30, [sp], #16
11400 MachineInstr *LDPXpost = BuildMI(MF, DebugLoc(), get(AArch64::LDPXpost))
11401 .addReg(AArch64::SP, RegState::Define)
11402 .addReg(AArch64::FP, RegState::Define)
11403 .addReg(AArch64::LR, RegState::Define)
11404 .addReg(AArch64::SP)
11405 .addImm(2);
11406 Et = MBB.insert(Et, LDPXpost);
11407 } else {
11408 // Insert a save before the outlined region
11409 MachineInstr *STRXpre = BuildMI(MF, DebugLoc(), get(AArch64::STRXpre))
11410 .addReg(AArch64::SP, RegState::Define)
11411 .addReg(AArch64::LR)
11412 .addReg(AArch64::SP)
11413 .addImm(-16);
11414 It = MBB.insert(It, STRXpre);
11415
11416 if (MF.getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF)) {
11417 CFIInstBuilder CFIBuilder(MBB, It, MachineInstr::FrameSetup);
11418
11419 // Add a CFI saying the stack was moved 16 B down.
11420 CFIBuilder.buildDefCFAOffset(16);
11421
11422 // Add a CFI saying that the LR that we want to find is now 16 B higher
11423 // than before.
11424 CFIBuilder.buildOffset(AArch64::LR, -16);
11425 }
11426
11427 // Insert a restore before the terminator for the function.
11428 MachineInstr *LDRXpost = BuildMI(MF, DebugLoc(), get(AArch64::LDRXpost))
11429 .addReg(AArch64::SP, RegState::Define)
11430 .addReg(AArch64::LR, RegState::Define)
11431 .addReg(AArch64::SP)
11432 .addImm(16);
11433 Et = MBB.insert(Et, LDRXpost);
11434 }
11435 }
11436
11437 auto RASignCondition = FI->getSignReturnAddressCondition();
11438 bool ShouldSignReturnAddr = AArch64FunctionInfo::shouldSignReturnAddress(
11439 RASignCondition, !IsLeafFunction);
11440
11441 // If this is a tail call outlined function, then there's already a return.
11442 if (OF.FrameConstructionID == MachineOutlinerTailCall ||
11443 OF.FrameConstructionID == MachineOutlinerThunk) {
11444 signOutlinedFunction(MF, MBB, this, ShouldSignReturnAddr);
11445 return;
11446 }
11447
11448 // It's not a tail call, so we have to insert the return ourselves.
11449
11450 // LR has to be a live in so that we can return to it.
11451 if (!MBB.isLiveIn(AArch64::LR))
11452 MBB.addLiveIn(AArch64::LR);
11453
11454 MachineInstr *ret = BuildMI(MF, DebugLoc(), get(AArch64::RET))
11455 .addReg(AArch64::LR);
11456 MBB.insert(MBB.end(), ret);
11457
11458 signOutlinedFunction(MF, MBB, this, ShouldSignReturnAddr);
11459
11460 FI->setOutliningStyle("Function");
11461
11462 // Did we have to modify the stack by saving the link register?
11463 if (OF.FrameConstructionID != MachineOutlinerDefault)
11464 return;
11465
11466 // We modified the stack.
11467 // Walk over the basic block and fix up all the stack accesses.
11468 fixupPostOutline(MBB);
11469}
11470
11471MachineBasicBlock::iterator AArch64InstrInfo::insertOutlinedCall(
11474
11475 // Are we tail calling?
11476 if (C.CallConstructionID == MachineOutlinerTailCall) {
11477 // If yes, then we can just branch to the label.
11478 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::TCRETURNdi))
11479 .addGlobalAddress(M.getNamedValue(MF.getName()))
11480 .addImm(0));
11481 return It;
11482 }
11483
11484 // Are we saving the link register?
11485 if (C.CallConstructionID == MachineOutlinerNoLRSave ||
11486 C.CallConstructionID == MachineOutlinerThunk) {
11487 // No, so just insert the call.
11488 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::BL))
11489 .addGlobalAddress(M.getNamedValue(MF.getName())));
11490 return It;
11491 }
11492
11493 // We want to return the spot where we inserted the call.
11495
11496 // Instructions for saving and restoring LR around the call instruction we're
11497 // going to insert.
11498 MachineInstr *Save;
11499 MachineInstr *Restore;
11500 // Can we save to a register?
11501 if (C.CallConstructionID == MachineOutlinerRegSave) {
11502 // FIXME: This logic should be sunk into a target-specific interface so that
11503 // we don't have to recompute the register.
11504 Register Reg = findRegisterToSaveLRTo(C);
11505 assert(Reg && "No callee-saved register available?");
11506
11507 // LR has to be a live in so that we can save it.
11508 if (!MBB.isLiveIn(AArch64::LR))
11509 MBB.addLiveIn(AArch64::LR);
11510
11511 // Save and restore LR from Reg.
11512 Save = BuildMI(MF, DebugLoc(), get(AArch64::ORRXrs), Reg)
11513 .addReg(AArch64::XZR)
11514 .addReg(AArch64::LR)
11515 .addImm(0);
11516 Restore = BuildMI(MF, DebugLoc(), get(AArch64::ORRXrs), AArch64::LR)
11517 .addReg(AArch64::XZR)
11518 .addReg(Reg)
11519 .addImm(0);
11520 } else {
11521 // We have the default case. Save and restore from SP.
11522 Save = BuildMI(MF, DebugLoc(), get(AArch64::STRXpre))
11523 .addReg(AArch64::SP, RegState::Define)
11524 .addReg(AArch64::LR)
11525 .addReg(AArch64::SP)
11526 .addImm(-16);
11527 Restore = BuildMI(MF, DebugLoc(), get(AArch64::LDRXpost))
11528 .addReg(AArch64::SP, RegState::Define)
11529 .addReg(AArch64::LR, RegState::Define)
11530 .addReg(AArch64::SP)
11531 .addImm(16);
11532 }
11533
11534 It = MBB.insert(It, Save);
11535 It++;
11536
11537 // Insert the call.
11538 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::BL))
11539 .addGlobalAddress(M.getNamedValue(MF.getName())));
11540 CallPt = It;
11541 It++;
11542
11543 It = MBB.insert(It, Restore);
11544 return CallPt;
11545}
11546
11547bool AArch64InstrInfo::shouldOutlineFromFunctionByDefault(
11548 MachineFunction &MF) const {
11549 return MF.getFunction().hasMinSize();
11550}
11551
11552void AArch64InstrInfo::buildClearRegister(Register Reg, MachineBasicBlock &MBB,
11554 DebugLoc &DL,
11555 bool AllowSideEffects) const {
11556 const MachineFunction &MF = *MBB.getParent();
11557 const AArch64Subtarget &STI = MF.getSubtarget<AArch64Subtarget>();
11558 const AArch64RegisterInfo &TRI = *STI.getRegisterInfo();
11559
11560 if (TRI.isGeneralPurposeRegister(MF, Reg)) {
11561 BuildMI(MBB, Iter, DL, get(AArch64::MOVZXi), Reg).addImm(0).addImm(0);
11562 } else if (STI.isSVEorStreamingSVEAvailable()) {
11563 BuildMI(MBB, Iter, DL, get(AArch64::DUP_ZI_D), Reg)
11564 .addImm(0)
11565 .addImm(0);
11566 } else if (STI.isNeonAvailable()) {
11567 BuildMI(MBB, Iter, DL, get(AArch64::MOVIv2d_ns), Reg)
11568 .addImm(0);
11569 } else {
11570 // No Advanced SIMD (streaming-compatible without SVE, or +nosimd), so use
11571 // `fmov d...` instead of `movi v...`; writing `d` also clears the upper
11572 // 64 bits.
11573 assert(STI.hasFPARMv8() && "Expected FP to be available.");
11574 Register Reg64 = TRI.getSubReg(Reg, AArch64::dsub);
11575 BuildMI(MBB, Iter, DL, get(AArch64::FMOVD0), Reg64);
11576 }
11577}
11578
11579std::optional<DestSourcePair>
11581
11582 // AArch64::ORRWrs and AArch64::ORRXrs with WZR/XZR reg
11583 // and zero immediate operands used as an alias for mov instruction.
11584 if ((MI.getOpcode() == AArch64::ORRWrs &&
11585 MI.getOperand(1).getReg() == AArch64::WZR &&
11586 MI.getOperand(3).getImm() == 0x0) ||
11587 (MI.getOpcode() == AArch64::ORRWrr &&
11588 MI.getOperand(1).getReg() == AArch64::WZR)) {
11589 // Check that the w->w move is not a zero-extending w->x mov.
11590 if ((MI.getOperand(0).getReg().isPhysical() &&
11591 MI.findRegisterDefOperandIdx(
11592 getXRegFromWReg(MI.getOperand(0).getReg()),
11593 /*TRI=*/nullptr) == -1) ||
11594 (MI.getOperand(0).getReg().isVirtual() &&
11595 !MI.getOperand(0).getSubReg()))
11596 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11597 }
11598
11599 if (MI.getOpcode() == AArch64::ORRXrs &&
11600 MI.getOperand(1).getReg() == AArch64::XZR &&
11601 MI.getOperand(3).getImm() == 0x0)
11602 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11603
11604 return std::nullopt;
11605}
11606
11607std::optional<DestSourcePair>
11609 if ((MI.getOpcode() == AArch64::ORRWrs &&
11610 MI.getOperand(1).getReg() == AArch64::WZR &&
11611 MI.getOperand(3).getImm() == 0x0) ||
11612 (MI.getOpcode() == AArch64::ORRWrr &&
11613 MI.getOperand(1).getReg() == AArch64::WZR))
11614 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11615 return std::nullopt;
11616}
11617
11618std::optional<RegImmPair>
11619AArch64InstrInfo::isAddImmediate(const MachineInstr &MI, Register Reg) const {
11620 int Sign = 1;
11621 int64_t Offset = 0;
11622
11623 // TODO: Handle cases where Reg is a super- or sub-register of the
11624 // destination register.
11625 const MachineOperand &Op0 = MI.getOperand(0);
11626 if (!Op0.isReg() || Reg != Op0.getReg())
11627 return std::nullopt;
11628
11629 switch (MI.getOpcode()) {
11630 default:
11631 return std::nullopt;
11632 case AArch64::SUBWri:
11633 case AArch64::SUBXri:
11634 case AArch64::SUBSWri:
11635 case AArch64::SUBSXri:
11636 Sign *= -1;
11637 [[fallthrough]];
11638 case AArch64::ADDSWri:
11639 case AArch64::ADDSXri:
11640 case AArch64::ADDWri:
11641 case AArch64::ADDXri: {
11642 // TODO: Third operand can be global address (usually some string).
11643 if (!MI.getOperand(0).isReg() || !MI.getOperand(1).isReg() ||
11644 !MI.getOperand(2).isImm())
11645 return std::nullopt;
11646 int Shift = MI.getOperand(3).getImm();
11647 assert((Shift == 0 || Shift == 12) && "Shift can be either 0 or 12");
11648 Offset = Sign * (MI.getOperand(2).getImm() << Shift);
11649 }
11650 }
11651 return RegImmPair{MI.getOperand(1).getReg(), Offset};
11652}
11653
11654/// If the given ORR instruction is a copy, and \p DescribedReg overlaps with
11655/// the destination register then, if possible, describe the value in terms of
11656/// the source register.
11657static std::optional<ParamLoadedValue>
11659 const TargetInstrInfo *TII,
11660 const TargetRegisterInfo *TRI) {
11661 auto DestSrc = TII->isCopyLikeInstr(MI);
11662 if (!DestSrc)
11663 return std::nullopt;
11664
11665 Register DestReg = DestSrc->Destination->getReg();
11666 Register SrcReg = DestSrc->Source->getReg();
11667
11668 if (!DestReg.isValid() || !SrcReg.isValid())
11669 return std::nullopt;
11670
11671 auto Expr = DIExpression::get(MI.getMF()->getFunction().getContext(), {});
11672
11673 // If the described register is the destination, just return the source.
11674 if (DestReg == DescribedReg)
11675 return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
11676
11677 // ORRWrs zero-extends to 64-bits, so we need to consider such cases.
11678 if (MI.getOpcode() == AArch64::ORRWrs &&
11679 TRI->isSuperRegister(DestReg, DescribedReg))
11680 return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
11681
11682 // We may need to describe the lower part of a ORRXrs move.
11683 if (MI.getOpcode() == AArch64::ORRXrs &&
11684 TRI->isSubRegister(DestReg, DescribedReg)) {
11685 Register SrcSubReg = TRI->getSubReg(SrcReg, AArch64::sub_32);
11686 return ParamLoadedValue(MachineOperand::CreateReg(SrcSubReg, false), Expr);
11687 }
11688
11689 assert(!TRI->isSuperOrSubRegisterEq(DestReg, DescribedReg) &&
11690 "Unhandled ORR[XW]rs copy case");
11691
11692 return std::nullopt;
11693}
11694
11695bool AArch64InstrInfo::isFunctionSafeToSplit(const MachineFunction &MF) const {
11696 // Functions cannot be split to different sections on AArch64 if they have
11697 // a red zone. This is because relaxing a cross-section branch may require
11698 // incrementing the stack pointer to spill a register, which would overwrite
11699 // the red zone.
11700 if (MF.getInfo<AArch64FunctionInfo>()->hasRedZone().value_or(true))
11701 return false;
11702
11704}
11705
11706bool AArch64InstrInfo::isMBBSafeToSplitToCold(
11707 const MachineBasicBlock &MBB) const {
11708 // Asm Goto blocks can contain conditional branches to goto labels, which can
11709 // get moved out of range of the branch instruction.
11710 auto isAsmGoto = [](const MachineInstr &MI) {
11711 return MI.getOpcode() == AArch64::INLINEASM_BR;
11712 };
11713 if (llvm::any_of(MBB, isAsmGoto) || MBB.isInlineAsmBrIndirectTarget())
11714 return false;
11715
11716 // Because jump tables are label-relative instead of table-relative, they all
11717 // must be in the same section or relocation fixup handling will fail.
11718
11719 // Check if MBB is a jump table target
11720 const MachineJumpTableInfo *MJTI = MBB.getParent()->getJumpTableInfo();
11721 auto containsMBB = [&MBB](const MachineJumpTableEntry &JTE) {
11722 return llvm::is_contained(JTE.MBBs, &MBB);
11723 };
11724 if (MJTI != nullptr && llvm::any_of(MJTI->getJumpTables(), containsMBB))
11725 return false;
11726
11727 // Check if MBB contains a jump table lookup
11728 for (const MachineInstr &MI : MBB) {
11729 switch (MI.getOpcode()) {
11730 case TargetOpcode::G_BRJT:
11731 case AArch64::JumpTableDest32:
11732 case AArch64::JumpTableDest16:
11733 case AArch64::JumpTableDest8:
11734 return false;
11735 default:
11736 continue;
11737 }
11738 }
11739
11740 // MBB isn't a special case, so it's safe to be split to the cold section.
11741 return true;
11742}
11743
11744std::optional<ParamLoadedValue>
11745AArch64InstrInfo::describeLoadedValue(const MachineInstr &MI,
11746 Register Reg) const {
11747 const MachineFunction *MF = MI.getMF();
11748 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
11749 switch (MI.getOpcode()) {
11750 case AArch64::MOVZWi:
11751 case AArch64::MOVZXi: {
11752 // MOVZWi may be used for producing zero-extended 32-bit immediates in
11753 // 64-bit parameters, so we need to consider super-registers.
11754 if (!TRI->isSuperRegisterEq(MI.getOperand(0).getReg(), Reg))
11755 return std::nullopt;
11756
11757 if (!MI.getOperand(1).isImm())
11758 return std::nullopt;
11759 int64_t Immediate = MI.getOperand(1).getImm();
11760 int Shift = MI.getOperand(2).getImm();
11761 return ParamLoadedValue(MachineOperand::CreateImm(Immediate << Shift),
11762 nullptr);
11763 }
11764 case AArch64::ORRWrs:
11765 case AArch64::ORRXrs:
11766 return describeORRLoadedValue(MI, Reg, this, TRI);
11767 }
11768
11770}
11771
11772bool AArch64InstrInfo::isExtendLikelyToBeFolded(
11773 MachineInstr &ExtMI, MachineRegisterInfo &MRI) const {
11774 assert(ExtMI.getOpcode() == TargetOpcode::G_SEXT ||
11775 ExtMI.getOpcode() == TargetOpcode::G_ZEXT ||
11776 ExtMI.getOpcode() == TargetOpcode::G_ANYEXT);
11777
11778 // Anyexts are nops.
11779 if (ExtMI.getOpcode() == TargetOpcode::G_ANYEXT)
11780 return true;
11781
11782 Register DefReg = ExtMI.getOperand(0).getReg();
11783 if (!MRI.hasOneNonDBGUse(DefReg))
11784 return false;
11785
11786 // It's likely that a sext/zext as a G_PTR_ADD offset will be folded into an
11787 // addressing mode.
11788 auto *UserMI = &*MRI.use_instr_nodbg_begin(DefReg);
11789 return UserMI->getOpcode() == TargetOpcode::G_PTR_ADD;
11790}
11791
11792uint64_t AArch64InstrInfo::getElementSizeForOpcode(unsigned Opc) const {
11793 return get(Opc).TSFlags & AArch64::ElementSizeMask;
11794}
11795
11796bool AArch64InstrInfo::isPTestLikeOpcode(unsigned Opc) const {
11797 return get(Opc).TSFlags & AArch64::InstrFlagIsPTestLike;
11798}
11799
11800bool AArch64InstrInfo::isWhileOpcode(unsigned Opc) const {
11801 return get(Opc).TSFlags & AArch64::InstrFlagIsWhile;
11802}
11803
11804unsigned int
11805AArch64InstrInfo::getTailDuplicateSize(CodeGenOptLevel OptLevel) const {
11806 return OptLevel >= CodeGenOptLevel::Aggressive ? 6 : 2;
11807}
11808
11809bool AArch64InstrInfo::isLegalAddressingMode(unsigned NumBytes, int64_t Offset,
11810 unsigned Scale) const {
11811 if (Offset && Scale)
11812 return false;
11813
11814 // Check Reg + Imm
11815 if (!Scale) {
11816 // 9-bit signed offset
11817 if (isInt<9>(Offset))
11818 return true;
11819
11820 // 12-bit unsigned offset
11821 unsigned Shift = Log2_64(NumBytes);
11822 if (NumBytes && Offset > 0 && (Offset / NumBytes) <= (1LL << 12) - 1 &&
11823 // Must be a multiple of NumBytes (NumBytes is a power of 2)
11824 (Offset >> Shift) << Shift == Offset)
11825 return true;
11826 return false;
11827 }
11828
11829 // Check reg1 + SIZE_IN_BYTES * reg2 and reg1 + reg2
11830 return Scale == 1 || (Scale > 0 && Scale == NumBytes);
11831}
11832
11834 if (MF.getSubtarget<AArch64Subtarget>().hardenSlsBlr())
11835 return AArch64::BLRNoIP;
11836 else
11837 return AArch64::BLR;
11838}
11839
11841 DebugLoc DL) const {
11842 MachineBasicBlock::iterator InsertPt = MBB.getFirstTerminator();
11843 auto Builder = BuildMI(MBB, InsertPt, DL, get(AArch64::PAUTH_EPILOGUE))
11845
11846 MachineFunction &MF = *MBB.getParent();
11847 const auto *AFI = MF.getInfo<AArch64FunctionInfo>();
11848 auto &AFL = *static_cast<const AArch64FrameLowering *>(
11849 MF.getSubtarget().getFrameLowering());
11850 if (AFL.getArgumentStackToRestore(MF, MBB)) {
11851 Builder.addReg(AArch64::X17, RegState::ImplicitDefine);
11852 Builder.addReg(AArch64::X16, RegState::ImplicitDefine);
11853 if (AFI->branchProtectionPAuthLR())
11854 Builder.addReg(AArch64::X15, RegState::ImplicitDefine);
11855 return;
11856 }
11857
11858 if (AFI->branchProtectionPAuthLR() && !Subtarget.hasPAuthLR())
11859 Builder.addReg(AArch64::X16, RegState::ImplicitDefine);
11860}
11861
11863AArch64InstrInfo::probedStackAlloc(MachineBasicBlock::iterator MBBI,
11864 Register TargetReg, bool FrameSetup) const {
11865 assert(TargetReg != AArch64::SP && "New top of stack cannot already be in SP");
11866
11867 MachineBasicBlock &MBB = *MBBI->getParent();
11868 MachineFunction &MF = *MBB.getParent();
11869 const AArch64InstrInfo *TII =
11870 MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
11871 int64_t ProbeSize = MF.getInfo<AArch64FunctionInfo>()->getStackProbeSize();
11872 DebugLoc DL = MBB.findDebugLoc(MBBI);
11873
11874 MachineFunction::iterator MBBInsertPoint = std::next(MBB.getIterator());
11875 MachineBasicBlock *LoopTestMBB =
11876 MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11877 MF.insert(MBBInsertPoint, LoopTestMBB);
11878 MachineBasicBlock *LoopBodyMBB =
11879 MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11880 MF.insert(MBBInsertPoint, LoopBodyMBB);
11881 MachineBasicBlock *ExitMBB = MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11882 MF.insert(MBBInsertPoint, ExitMBB);
11883 MachineInstr::MIFlag Flags =
11885
11886 // LoopTest:
11887 // SUB SP, SP, #ProbeSize
11888 emitFrameOffset(*LoopTestMBB, LoopTestMBB->end(), DL, AArch64::SP,
11889 AArch64::SP, StackOffset::getFixed(-ProbeSize), TII, Flags);
11890
11891 // CMP SP, TargetReg
11892 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(AArch64::SUBSXrx64),
11893 AArch64::XZR)
11894 .addReg(AArch64::SP)
11895 .addReg(TargetReg)
11897 .setMIFlags(Flags);
11898
11899 // B.<Cond> LoopExit
11900 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(AArch64::Bcc))
11902 .addMBB(ExitMBB)
11903 .setMIFlags(Flags);
11904
11905 // LDR XZR, [SP]
11906 BuildMI(*LoopBodyMBB, LoopBodyMBB->end(), DL, TII->get(AArch64::LDRXui))
11907 .addDef(AArch64::XZR)
11908 .addReg(AArch64::SP)
11909 .addImm(0)
11913 Align(8)))
11914 .setMIFlags(Flags);
11915
11916 // B loop
11917 BuildMI(*LoopBodyMBB, LoopBodyMBB->end(), DL, TII->get(AArch64::B))
11918 .addMBB(LoopTestMBB)
11919 .setMIFlags(Flags);
11920
11921 // LoopExit:
11922 // MOV SP, TargetReg
11923 BuildMI(*ExitMBB, ExitMBB->end(), DL, TII->get(AArch64::ADDXri), AArch64::SP)
11924 .addReg(TargetReg)
11925 .addImm(0)
11927 .setMIFlags(Flags);
11928
11929 // LDR XZR, [SP]
11930 BuildMI(*ExitMBB, ExitMBB->end(), DL, TII->get(AArch64::LDRXui))
11931 .addReg(AArch64::XZR, RegState::Define)
11932 .addReg(AArch64::SP)
11933 .addImm(0)
11934 .setMIFlags(Flags);
11935
11936 ExitMBB->splice(ExitMBB->end(), &MBB, std::next(MBBI), MBB.end());
11938
11939 LoopTestMBB->addSuccessor(ExitMBB);
11940 LoopTestMBB->addSuccessor(LoopBodyMBB);
11941 LoopBodyMBB->addSuccessor(LoopTestMBB);
11942 MBB.addSuccessor(LoopTestMBB);
11943
11944 // Update liveins.
11945 if (MF.getRegInfo().reservedRegsFrozen())
11946 fullyRecomputeLiveIns({ExitMBB, LoopBodyMBB, LoopTestMBB});
11947
11948 return ExitMBB->begin();
11949}
11950
11951namespace {
11952class AArch64PipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
11953 MachineFunction *MF;
11954 const TargetInstrInfo *TII;
11955 const TargetRegisterInfo *TRI;
11956 MachineRegisterInfo &MRI;
11957
11958 /// The block of the loop
11959 MachineBasicBlock *LoopBB;
11960 /// The conditional branch of the loop
11961 MachineInstr *CondBranch;
11962 /// The compare instruction for loop control
11963 MachineInstr *Comp;
11964 /// The number of the operand of the loop counter value in Comp
11965 unsigned CompCounterOprNum;
11966 /// The instruction that updates the loop counter value
11967 MachineInstr *Update;
11968 /// The number of the operand of the loop counter value in Update
11969 unsigned UpdateCounterOprNum;
11970 /// The initial value of the loop counter
11971 Register Init;
11972 /// True iff Update is a predecessor of Comp
11973 bool IsUpdatePriorComp;
11974
11975 /// The normalized condition used by createTripCountGreaterCondition()
11976 SmallVector<MachineOperand, 4> Cond;
11977
11978public:
11979 AArch64PipelinerLoopInfo(MachineBasicBlock *LoopBB, MachineInstr *CondBranch,
11980 MachineInstr *Comp, unsigned CompCounterOprNum,
11981 MachineInstr *Update, unsigned UpdateCounterOprNum,
11982 Register Init, bool IsUpdatePriorComp,
11983 const SmallVectorImpl<MachineOperand> &Cond)
11984 : MF(Comp->getParent()->getParent()),
11985 TII(MF->getSubtarget().getInstrInfo()),
11986 TRI(MF->getSubtarget().getRegisterInfo()), MRI(MF->getRegInfo()),
11987 LoopBB(LoopBB), CondBranch(CondBranch), Comp(Comp),
11988 CompCounterOprNum(CompCounterOprNum), Update(Update),
11989 UpdateCounterOprNum(UpdateCounterOprNum), Init(Init),
11990 IsUpdatePriorComp(IsUpdatePriorComp), Cond(Cond.begin(), Cond.end()) {}
11991
11992 bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
11993 // Make the instructions for loop control be placed in stage 0.
11994 // The predecessors of Comp are considered by the caller.
11995 return MI == Comp;
11996 }
11997
11998 std::optional<bool> createTripCountGreaterCondition(
11999 int TC, MachineBasicBlock &MBB,
12000 SmallVectorImpl<MachineOperand> &CondParam) override {
12001 // A branch instruction will be inserted as "if (Cond) goto epilogue".
12002 // Cond is normalized for such use.
12003 // The predecessors of the branch are assumed to have already been inserted.
12004 CondParam = Cond;
12005 return {};
12006 }
12007
12008 void createRemainingIterationsGreaterCondition(
12009 int TC, MachineBasicBlock &MBB, SmallVectorImpl<MachineOperand> &Cond,
12010 DenseMap<MachineInstr *, MachineInstr *> &LastStage0Insts) override;
12011
12012 void setPreheader(MachineBasicBlock *NewPreheader) override {}
12013
12014 void adjustTripCount(int TripCountAdjust) override {}
12015
12016 bool isMVEExpanderSupported() override { return true; }
12017};
12018} // namespace
12019
12020/// Clone an instruction from MI. The register of ReplaceOprNum-th operand
12021/// is replaced by ReplaceReg. The output register is newly created.
12022/// The other operands are unchanged from MI.
12023static Register cloneInstr(const MachineInstr *MI, unsigned ReplaceOprNum,
12024 Register ReplaceReg, MachineBasicBlock &MBB,
12025 MachineBasicBlock::iterator InsertTo) {
12026 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
12027 const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo();
12028 MachineInstr *NewMI = MBB.getParent()->CloneMachineInstr(MI);
12029 Register Result = 0;
12030 for (unsigned I = 0; I < NewMI->getNumOperands(); ++I) {
12031 if (I == 0 && NewMI->getOperand(0).getReg().isVirtual()) {
12032 Result = MRI.createVirtualRegister(
12033 MRI.getRegClass(NewMI->getOperand(0).getReg()));
12034 NewMI->getOperand(I).setReg(Result);
12035 } else if (I == ReplaceOprNum) {
12036 MRI.constrainRegClass(ReplaceReg, TII->getRegClass(NewMI->getDesc(), I));
12037 NewMI->getOperand(I).setReg(ReplaceReg);
12038 }
12039 }
12040 MBB.insert(InsertTo, NewMI);
12041 return Result;
12042}
12043
12044void AArch64PipelinerLoopInfo::createRemainingIterationsGreaterCondition(
12047 // Create and accumulate conditions for next TC iterations.
12048 // Example:
12049 // SUBSXrr N, counter, implicit-def $nzcv # compare instruction for the last
12050 // # iteration of the kernel
12051 //
12052 // # insert the following instructions
12053 // cond = CSINCXr 0, 0, C, implicit $nzcv
12054 // counter = ADDXri counter, 1 # clone from this->Update
12055 // SUBSXrr n, counter, implicit-def $nzcv # clone from this->Comp
12056 // cond = CSINCXr cond, cond, C, implicit $nzcv
12057 // ... (repeat TC times)
12058 // SUBSXri cond, 0, implicit-def $nzcv
12059
12060 assert(CondBranch->getOpcode() == AArch64::Bcc);
12061 // CondCode to exit the loop
12063 (AArch64CC::CondCode)CondBranch->getOperand(0).getImm();
12064 if (CondBranch->getOperand(1).getMBB() == LoopBB)
12066
12067 // Accumulate conditions to exit the loop
12068 Register AccCond = AArch64::XZR;
12069
12070 // If CC holds, CurCond+1 is returned; otherwise CurCond is returned.
12071 auto AccumulateCond = [&](Register CurCond,
12073 Register NewCond = MRI.createVirtualRegister(&AArch64::GPR64commonRegClass);
12074 BuildMI(MBB, MBB.end(), Comp->getDebugLoc(), TII->get(AArch64::CSINCXr))
12075 .addReg(NewCond, RegState::Define)
12076 .addReg(CurCond)
12077 .addReg(CurCond)
12079 return NewCond;
12080 };
12081
12082 if (!LastStage0Insts.empty() && LastStage0Insts[Comp]->getParent() == &MBB) {
12083 // Update and Comp for I==0 are already exists in MBB
12084 // (MBB is an unrolled kernel)
12085 Register Counter;
12086 for (int I = 0; I <= TC; ++I) {
12087 Register NextCounter;
12088 if (I != 0)
12089 NextCounter =
12090 cloneInstr(Comp, CompCounterOprNum, Counter, MBB, MBB.end());
12091
12092 AccCond = AccumulateCond(AccCond, CC);
12093
12094 if (I != TC) {
12095 if (I == 0) {
12096 if (Update != Comp && IsUpdatePriorComp) {
12097 Counter =
12098 LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
12099 NextCounter = cloneInstr(Update, UpdateCounterOprNum, Counter, MBB,
12100 MBB.end());
12101 } else {
12102 // can use already calculated value
12103 NextCounter = LastStage0Insts[Update]->getOperand(0).getReg();
12104 }
12105 } else if (Update != Comp) {
12106 NextCounter =
12107 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
12108 }
12109 }
12110 Counter = NextCounter;
12111 }
12112 } else {
12113 Register Counter;
12114 if (LastStage0Insts.empty()) {
12115 // use initial counter value (testing if the trip count is sufficient to
12116 // be executed by pipelined code)
12117 Counter = Init;
12118 if (IsUpdatePriorComp)
12119 Counter =
12120 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
12121 } else {
12122 // MBB is an epilogue block. LastStage0Insts[Comp] is in the kernel block.
12123 Counter = LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
12124 }
12125
12126 for (int I = 0; I <= TC; ++I) {
12127 Register NextCounter;
12128 NextCounter =
12129 cloneInstr(Comp, CompCounterOprNum, Counter, MBB, MBB.end());
12130 AccCond = AccumulateCond(AccCond, CC);
12131 if (I != TC && Update != Comp)
12132 NextCounter =
12133 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
12134 Counter = NextCounter;
12135 }
12136 }
12137
12138 // If AccCond == 0, the remainder is greater than TC.
12139 BuildMI(MBB, MBB.end(), Comp->getDebugLoc(), TII->get(AArch64::SUBSXri))
12140 .addReg(AArch64::XZR, RegState::Define | RegState::Dead)
12141 .addReg(AccCond)
12142 .addImm(0)
12143 .addImm(0);
12144 Cond.clear();
12146}
12147
12148static void extractPhiReg(const MachineInstr &Phi, const MachineBasicBlock *MBB,
12149 Register &RegMBB, Register &RegOther) {
12150 assert(Phi.getNumOperands() == 5);
12151 if (Phi.getOperand(2).getMBB() == MBB) {
12152 RegMBB = Phi.getOperand(1).getReg();
12153 RegOther = Phi.getOperand(3).getReg();
12154 } else {
12155 assert(Phi.getOperand(4).getMBB() == MBB);
12156 RegMBB = Phi.getOperand(3).getReg();
12157 RegOther = Phi.getOperand(1).getReg();
12158 }
12159}
12160
12162 if (!Reg.isVirtual())
12163 return false;
12164 const MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();
12165 return MRI.getDefBlock(Reg) != BB;
12166}
12167
12168/// If Reg is an induction variable, return true and set some parameters
12169static bool getIndVarInfo(Register Reg, const MachineBasicBlock *LoopBB,
12170 MachineInstr *&UpdateInst,
12171 unsigned &UpdateCounterOprNum, Register &InitReg,
12172 bool &IsUpdatePriorComp) {
12173 // Example:
12174 //
12175 // Preheader:
12176 // InitReg = ...
12177 // LoopBB:
12178 // Reg0 = PHI (InitReg, Preheader), (Reg1, LoopBB)
12179 // Reg = COPY Reg0 ; COPY is ignored.
12180 // Reg1 = ADD Reg, #1; UpdateInst. Incremented by a loop invariant value.
12181 // ; Reg is the value calculated in the previous
12182 // ; iteration, so IsUpdatePriorComp == false.
12183
12184 if (LoopBB->pred_size() != 2)
12185 return false;
12186 if (!Reg.isVirtual())
12187 return false;
12188 const MachineRegisterInfo &MRI = LoopBB->getParent()->getRegInfo();
12189 UpdateInst = nullptr;
12190 UpdateCounterOprNum = 0;
12191 InitReg = 0;
12192 IsUpdatePriorComp = true;
12193 Register CurReg = Reg;
12194 while (true) {
12195 MachineInstr *Def = MRI.getVRegDef(CurReg);
12196 if (Def->getParent() != LoopBB)
12197 return false;
12198 if (Def->isCopy()) {
12199 // Ignore copy instructions unless they contain subregisters
12200 if (Def->getOperand(0).getSubReg() || Def->getOperand(1).getSubReg())
12201 return false;
12202 CurReg = Def->getOperand(1).getReg();
12203 } else if (Def->isPHI()) {
12204 if (InitReg != 0)
12205 return false;
12206 if (!UpdateInst)
12207 IsUpdatePriorComp = false;
12208 extractPhiReg(*Def, LoopBB, CurReg, InitReg);
12209 } else {
12210 if (UpdateInst)
12211 return false;
12212 switch (Def->getOpcode()) {
12213 case AArch64::ADDSXri:
12214 case AArch64::ADDSWri:
12215 case AArch64::SUBSXri:
12216 case AArch64::SUBSWri:
12217 case AArch64::ADDXri:
12218 case AArch64::ADDWri:
12219 case AArch64::SUBXri:
12220 case AArch64::SUBWri:
12221 UpdateInst = Def;
12222 UpdateCounterOprNum = 1;
12223 break;
12224 case AArch64::ADDSXrr:
12225 case AArch64::ADDSWrr:
12226 case AArch64::SUBSXrr:
12227 case AArch64::SUBSWrr:
12228 case AArch64::ADDXrr:
12229 case AArch64::ADDWrr:
12230 case AArch64::SUBXrr:
12231 case AArch64::SUBWrr:
12232 UpdateInst = Def;
12233 if (isDefinedOutside(Def->getOperand(2).getReg(), LoopBB))
12234 UpdateCounterOprNum = 1;
12235 else if (isDefinedOutside(Def->getOperand(1).getReg(), LoopBB))
12236 UpdateCounterOprNum = 2;
12237 else
12238 return false;
12239 break;
12240 default:
12241 return false;
12242 }
12243 CurReg = Def->getOperand(UpdateCounterOprNum).getReg();
12244 }
12245
12246 if (!CurReg.isVirtual())
12247 return false;
12248 if (Reg == CurReg)
12249 break;
12250 }
12251
12252 if (!UpdateInst)
12253 return false;
12254
12255 return true;
12256}
12257
12258std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
12260 // Accept loops that meet the following conditions
12261 // * The conditional branch is BCC
12262 // * The compare instruction is ADDS/SUBS/WHILEXX
12263 // * One operand of the compare is an induction variable and the other is a
12264 // loop invariant value
12265 // * The induction variable is incremented/decremented by a single instruction
12266 // * Does not contain CALL or instructions which have unmodeled side effects
12267
12268 for (MachineInstr &MI : *LoopBB)
12269 if (MI.isCall() || MI.hasUnmodeledSideEffects())
12270 // This instruction may use NZCV, which interferes with the instruction to
12271 // be inserted for loop control.
12272 return nullptr;
12273
12274 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
12276 if (analyzeBranch(*LoopBB, TBB, FBB, Cond))
12277 return nullptr;
12278
12279 // Infinite loops are not supported
12280 if (TBB == LoopBB && FBB == LoopBB)
12281 return nullptr;
12282
12283 // Must be conditional branch
12284 if (TBB != LoopBB && FBB == nullptr)
12285 return nullptr;
12286
12287 assert((TBB == LoopBB || FBB == LoopBB) &&
12288 "The Loop must be a single-basic-block loop");
12289
12290 MachineInstr *CondBranch = &*LoopBB->getFirstTerminator();
12292
12293 if (CondBranch->getOpcode() != AArch64::Bcc)
12294 return nullptr;
12295
12296 // Normalization for createTripCountGreaterCondition()
12297 if (TBB == LoopBB)
12299
12300 MachineInstr *Comp = nullptr;
12301 unsigned CompCounterOprNum = 0;
12302 for (MachineInstr &MI : reverse(*LoopBB)) {
12303 if (MI.modifiesRegister(AArch64::NZCV, &TRI)) {
12304 // Guarantee that the compare is SUBS/ADDS/WHILEXX and that one of the
12305 // operands is a loop invariant value
12306
12307 switch (MI.getOpcode()) {
12308 case AArch64::SUBSXri:
12309 case AArch64::SUBSWri:
12310 case AArch64::ADDSXri:
12311 case AArch64::ADDSWri:
12312 Comp = &MI;
12313 CompCounterOprNum = 1;
12314 break;
12315 case AArch64::ADDSWrr:
12316 case AArch64::ADDSXrr:
12317 case AArch64::SUBSWrr:
12318 case AArch64::SUBSXrr:
12319 Comp = &MI;
12320 break;
12321 default:
12322 if (isWhileOpcode(MI.getOpcode())) {
12323 Comp = &MI;
12324 break;
12325 }
12326 return nullptr;
12327 }
12328
12329 if (CompCounterOprNum == 0) {
12330 if (isDefinedOutside(Comp->getOperand(1).getReg(), LoopBB))
12331 CompCounterOprNum = 2;
12332 else if (isDefinedOutside(Comp->getOperand(2).getReg(), LoopBB))
12333 CompCounterOprNum = 1;
12334 else
12335 return nullptr;
12336 }
12337 break;
12338 }
12339 }
12340 if (!Comp)
12341 return nullptr;
12342
12343 MachineInstr *Update = nullptr;
12344 Register Init;
12345 bool IsUpdatePriorComp;
12346 unsigned UpdateCounterOprNum;
12347 if (!getIndVarInfo(Comp->getOperand(CompCounterOprNum).getReg(), LoopBB,
12348 Update, UpdateCounterOprNum, Init, IsUpdatePriorComp))
12349 return nullptr;
12350
12351 return std::make_unique<AArch64PipelinerLoopInfo>(
12352 LoopBB, CondBranch, Comp, CompCounterOprNum, Update, UpdateCounterOprNum,
12353 Init, IsUpdatePriorComp, Cond);
12354}
12355
12356/// verifyInstruction - Perform target specific instruction verification.
12357bool AArch64InstrInfo::verifyInstruction(const MachineInstr &MI,
12358 StringRef &ErrInfo) const {
12359 // Verify that immediate offsets on load/store instructions are within range.
12360 // Stack objects with an FI operand are excluded as they can be fixed up
12361 // during PEI.
12362 TypeSize Scale(0U, false), Width(0U, false);
12363 int64_t MinOffset, MaxOffset;
12364 if (getMemOpInfo(MI.getOpcode(), Scale, Width, MinOffset, MaxOffset)) {
12365 unsigned ImmIdx = getLoadStoreImmIdx(MI.getOpcode());
12366 if (MI.getOperand(ImmIdx).isImm() && !MI.getOperand(ImmIdx - 1).isFI()) {
12367 int64_t Imm = MI.getOperand(ImmIdx).getImm();
12368 if (Imm < MinOffset || Imm > MaxOffset) {
12369 ErrInfo = "Unexpected immediate on load/store instruction";
12370 return false;
12371 }
12372 }
12373 }
12374
12375 const MCInstrDesc &MCID = MI.getDesc();
12376 for (unsigned Op = 0; Op < MCID.getNumOperands(); Op++) {
12377 const MachineOperand &MO = MI.getOperand(Op);
12378 switch (MCID.operands()[Op].OperandType) {
12380 if (!MO.isImm() || MO.getImm() != 0) {
12381 ErrInfo = "OPERAND_IMPLICIT_IMM_0 should be 0";
12382 return false;
12383 }
12384 break;
12386 if (!MO.isImm() ||
12388 (AArch64_AM::getShiftValue(MO.getImm()) != 8 &&
12389 AArch64_AM::getShiftValue(MO.getImm()) != 16)) {
12390 ErrInfo = "OPERAND_SHIFT_MSL should be msl shift of 8 or 16";
12391 return false;
12392 }
12393 break;
12395 if (!MO.isImm() || (MO.getImm() != 0 && MO.getImm() != 1)) {
12396 ErrInfo = "OPERAND_IMM_UINT1 should be 0 or 1";
12397 return false;
12398 }
12399 break;
12401 if (!MO.isImm() || MO.getImm() <= 0 || MO.getImm() > 16) {
12402 ErrInfo = "OPERAND_IMM_UINT4plus1 should be in the range 1 to 16";
12403 return false;
12404 }
12405 break;
12407 if (!MO.isImm() || !isUInt<5>(MO.getImm())) {
12408 ErrInfo = "OPERAND_IMM_UINT5 should be in the range 0 to 31";
12409 return false;
12410 }
12411 break;
12413 if (!MO.isImm() || !isUInt<8>(MO.getImm())) {
12414 ErrInfo = "OPERAND_IMM_UINT8 should be in the range 0 to 255";
12415 return false;
12416 }
12417 break;
12418 default:
12419 break;
12420 }
12421 }
12422 return true;
12423}
12424
12425#define GET_INSTRINFO_HELPERS
12426#define GET_INSTRMAP_INFO
12427#include "AArch64GenInstrInfo.inc"
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static cl::opt< unsigned > BCCDisplacementBits("aarch64-bcc-offset-bits", cl::Hidden, cl::init(19), cl::desc("Restrict range of Bcc instructions (DEBUG)"))
static Register genNeg(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned MnegOpc, const TargetRegisterClass *RC)
genNeg - Helper to generate an intermediate negation of the second operand of Root
static bool isFrameStoreOpcode(int Opcode)
static cl::opt< unsigned > GatherOptSearchLimit("aarch64-search-limit", cl::Hidden, cl::init(2048), cl::desc("Restrict range of instructions to search for the " "machine-combiner gather pattern optimization"))
static bool getMaddPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Find instructions that can be turned into madd.
static AArch64CC::CondCode findCondCodeUsedByInstr(const MachineInstr &Instr)
Find a condition code used by the instruction.
static MachineInstr * genFusedMultiplyAcc(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC)
genFusedMultiplyAcc - Helper to generate fused multiply accumulate instructions.
static MachineInstr * genFusedMultiplyAccNeg(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned IdxMulOpd, unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC)
genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate instructions with an additional...
static bool isCombineInstrCandidate64(unsigned Opc)
static bool isFrameLoadOpcode(int Opcode)
static unsigned removeCopies(const MachineRegisterInfo &MRI, unsigned VReg)
static bool areCFlagsAccessedBetweenInstrs(MachineBasicBlock::iterator From, MachineBasicBlock::iterator To, const TargetRegisterInfo *TRI, const AccessKind AccessToCheck=AK_All)
True when condition flags are accessed (either by writing or reading) on the instruction trace starti...
static bool getFMAPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Floating-Point Support.
static bool isADDSRegImm(unsigned Opcode)
static bool isCheapCopy(const MachineInstr &MI, const AArch64RegisterInfo &RI)
static bool isANDOpcode(MachineInstr &MI)
static bool predictCompactUnwindFrameRecordForOutlinedFunction(std::vector< outliner::Candidate > &RepeatedSequenceLocs, const TargetRegisterInfo &TRI)
Predict what the above will answer, for use while costing candidates.
static void appendOffsetComment(int NumBytes, llvm::raw_string_ostream &Comment, StringRef RegScale={})
static unsigned sForm(MachineInstr &Instr)
Get opcode of S version of Instr.
static bool isCombineInstrSettingFlag(unsigned Opc)
static bool getFNEGPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
static bool getIndVarInfo(Register Reg, const MachineBasicBlock *LoopBB, MachineInstr *&UpdateInst, unsigned &UpdateCounterOprNum, Register &InitReg, bool &IsUpdatePriorComp)
If Reg is an induction variable, return true and set some parameters.
static bool canPairLdStOpc(unsigned FirstOpc, unsigned SecondOpc)
static bool mustAvoidNeonAtMBBI(const AArch64Subtarget &Subtarget, MachineBasicBlock &MBB, MachineBasicBlock::iterator I)
Returns true if in a streaming call site region without SME-FA64.
static bool isPostIndexLdStOpcode(unsigned Opcode)
Return true if the opcode is a post-index ld/st instruction, which really loads from base+0.
static std::optional< unsigned > getLFIInstSizeInBytes(const MachineInstr &MI)
Return the maximum number of bytes of code the specified instruction may be after LFI rewriting.
static unsigned getBranchDisplacementBits(unsigned Opc)
static cl::opt< unsigned > CBDisplacementBits("aarch64-cb-offset-bits", cl::Hidden, cl::init(9), cl::desc("Restrict range of CB instructions (DEBUG)"))
static std::optional< ParamLoadedValue > describeORRLoadedValue(const MachineInstr &MI, Register DescribedReg, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI)
If the given ORR instruction is a copy, and DescribedReg overlaps with the destination register then,...
static bool getFMULPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
static void appendReadRegExpr(SmallVectorImpl< char > &Expr, unsigned RegNum)
static MachineInstr * genMaddR(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, unsigned VR, const TargetRegisterClass *RC)
genMaddR - Generate madd instruction and combine mul and add using an extra virtual register Example ...
static Register cloneInstr(const MachineInstr *MI, unsigned ReplaceOprNum, Register ReplaceReg, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertTo)
Clone an instruction from MI.
static bool scaleOffset(unsigned Opc, int64_t &Offset)
static bool canCombineWithFMUL(MachineBasicBlock &MBB, MachineOperand &MO, unsigned MulOpc)
unsigned scaledOffsetOpcode(unsigned Opcode, unsigned &Scale)
static MachineInstr * genFusedMultiplyIdx(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC)
genFusedMultiplyIdx - Helper to generate fused multiply accumulate instructions.
static MachineInstr * genIndexedMultiply(MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxDupOp, unsigned MulOpc, const TargetRegisterClass *RC, MachineRegisterInfo &MRI)
Fold (FMUL x (DUP y lane)) into (FMUL_indexed x y lane)
static cl::opt< bool > UseCompactUnwindFrameRecordForOutlinedFunctions("aarch64-outliner-compact-unwind-frame", cl::Hidden, cl::init(true), cl::desc("Use a frame record for Mach-O non-leaf outlined functions"))
static bool shouldUseCompactUnwindFrameRecordForOutlinedFunction(const MachineBasicBlock &MBB)
Return true if the outlined function in MBB should save FP and LR as a frame record instead of saving...
static bool isSUBSRegImm(unsigned Opcode)
static bool UpdateOperandRegClass(MachineInstr &Instr)
static const TargetRegisterClass * getRegClass(const MachineInstr &MI, Register Reg)
static bool isInStreamingCallSiteRegion(MachineBasicBlock &MBB, MachineBasicBlock::iterator I)
Returns true if the instruction at I is in a streaming call site region, within a single basic block.
static bool canCmpInstrBeRemoved(MachineInstr &MI, MachineInstr &CmpInstr, int CmpValue, const TargetRegisterInfo &TRI, SmallVectorImpl< MachineInstr * > &CCUseInstrs, bool &IsInvertCC)
unsigned unscaledOffsetOpcode(unsigned Opcode)
static bool getLoadPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Search for patterns of LD instructions we can optimize.
static bool canInstrSubstituteCmpInstr(MachineInstr &MI, MachineInstr &CmpInstr, const TargetRegisterInfo &TRI)
Check if CmpInstr can be substituted by MI.
static UsedNZCV getUsedNZCV(AArch64CC::CondCode CC)
static bool isCombineInstrCandidateFP(const MachineInstr &Inst)
static bool isCompactUnwindFrameRecordEnabled(const MachineFunction &MF)
Return true if the frame-record form of the outlined prologue is enabled for the target of MF.
static void appendLoadRegExpr(SmallVectorImpl< char > &Expr, int64_t OffsetFromDefCFA)
static void appendConstantExpr(SmallVectorImpl< char > &Expr, int64_t Constant, dwarf::LocationAtom Operation)
static unsigned convertToNonFlagSettingOpc(const MachineInstr &MI)
Return the opcode that does not set flags when possible - otherwise return the original opcode.
static bool outliningCandidatesV8_3OpsConsensus(const outliner::Candidate &a, const outliner::Candidate &b)
static bool isCombineInstrCandidate32(unsigned Opc)
static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, SmallVectorImpl< MachineOperand > &Cond)
static unsigned offsetExtendOpcode(unsigned Opcode)
MachineOutlinerMBBFlags
@ LRUnavailableSomewhere
@ UnsafeRegsDead
static void loadRegPairFromStackSlot(const TargetRegisterInfo &TRI, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MCInstrDesc &MCID, Register DestReg, unsigned SubIdx0, unsigned SubIdx1, int FI, MachineMemOperand *MMO)
static void generateGatherLanePattern(MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned Pattern, unsigned NumLanes)
Generate optimized instruction sequence for gather load patterns to improve Memory-Level Parallelism ...
static bool getMiscPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns)
Find other MI combine patterns.
static bool outliningCandidatesSigningKeyConsensus(const outliner::Candidate &a, const outliner::Candidate &b)
static const MachineInstrBuilder & AddSubReg(const MachineInstrBuilder &MIB, MCRegister Reg, unsigned SubIdx, RegState State, const TargetRegisterInfo *TRI)
static bool outliningCandidatesSigningScopeConsensus(const outliner::Candidate &a, const outliner::Candidate &b)
static bool shouldClusterFI(const MachineFrameInfo &MFI, int FI1, int64_t Offset1, unsigned Opcode1, int FI2, int64_t Offset2, unsigned Opcode2)
static bool isValidCBExtend(int64_t Opc, AArch64_AM::ShiftExtendType Ext)
static cl::opt< unsigned > TBZDisplacementBits("aarch64-tbz-offset-bits", cl::Hidden, cl::init(14), cl::desc("Restrict range of TB[N]Z instructions (DEBUG)"))
static void extractPhiReg(const MachineInstr &Phi, const MachineBasicBlock *MBB, Register &RegMBB, Register &RegOther)
static MCCFIInstruction createDefCFAExpression(const TargetRegisterInfo &TRI, unsigned Reg, const StackOffset &Offset)
static bool isDefinedOutside(Register Reg, const MachineBasicBlock *BB)
static MachineInstr * genFusedMultiply(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC, FMAInstKind kind=FMAInstKind::Default, const Register *ReplacedAddend=nullptr)
genFusedMultiply - Generate fused multiply instructions.
static bool getGatherLanePattern(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, unsigned LoadLaneOpCode, unsigned NumLanes)
Check if the given instruction forms a gather load pattern that can be optimized for better Memory-Le...
static MachineInstr * genFusedMultiplyIdxNeg(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, DenseMap< Register, unsigned > &InstrIdxForVirtReg, unsigned IdxMulOpd, unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC)
genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate instructions with an additional...
static bool isCombineInstrCandidate(unsigned Opc)
static unsigned regOffsetOpcode(unsigned Opcode)
MachineOutlinerClass
Constants defining how certain sequences should be outlined.
@ MachineOutlinerTailCall
Emit a save, restore, call, and return.
@ MachineOutlinerRegSave
Emit a call and tail-call.
@ MachineOutlinerNoLRSave
Only emit a branch.
@ MachineOutlinerThunk
Emit a call and return.
@ MachineOutlinerDefault
static cl::opt< unsigned > BDisplacementBits("aarch64-b-offset-bits", cl::Hidden, cl::init(26), cl::desc("Restrict range of B instructions (DEBUG)"))
static bool areCFlagsAliveInSuccessors(const MachineBasicBlock *MBB)
Check if AArch64::NZCV should be alive in successors of MBB.
static void emitFrameOffsetAdj(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, int64_t Offset, unsigned Opc, const TargetInstrInfo *TII, MachineInstr::MIFlag Flag, bool NeedsWinCFI, bool *HasWinCFI, bool EmitCFAOffset, StackOffset CFAOffset, unsigned FrameReg)
static bool isCheapImmediate(const MachineInstr &MI, unsigned BitSize)
static cl::opt< unsigned > CBZDisplacementBits("aarch64-cbz-offset-bits", cl::Hidden, cl::init(19), cl::desc("Restrict range of CB[N]Z instructions (DEBUG)"))
static void genSubAdd2SubSub(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, unsigned IdxOpd1, DenseMap< Register, unsigned > &InstrIdxForVirtReg)
Do the following transformation A - (B + C) ==> (A - B) - C A - (B + C) ==> (A - C) - B.
static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg, unsigned *NewReg=nullptr)
static void signOutlinedFunction(MachineFunction &MF, MachineBasicBlock &MBB, const AArch64InstrInfo *TII, bool ShouldSignReturnAddr)
static MachineInstr * genFNegatedMAD(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs)
static bool canCombineWithMUL(MachineBasicBlock &MBB, MachineOperand &MO, unsigned MulOpc, unsigned ZeroReg)
static void storeRegPairToStackSlot(const TargetRegisterInfo &TRI, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertBefore, const MCInstrDesc &MCID, Register SrcReg, bool IsKill, unsigned SubIdx0, unsigned SubIdx1, int FI, MachineMemOperand *MMO)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned Imm
unsigned uint64_t
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
DXIL Forward Handle Accesses
@ Default
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
A set of register units.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
PowerPC Reduce CR logical Operation
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
This file contains some templates that are useful if you are working with the STL at all.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
This file defines the SmallSet class.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
Definition Debug.h:72
static bool canCombine(MachineBasicBlock &MBB, MachineOperand &MO, unsigned CombineOpc=0)
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
SignReturnAddress getSignReturnAddressCondition() const
void setOutliningStyle(const std::string &Style)
bool needsDwarfUnwindInfo(const MachineFunction &MF) const
std::optional< bool > hasRedZone() const
static bool shouldSignReturnAddress(SignReturnAddress Condition, bool IsLRSpilled)
static bool isHForm(const MachineInstr &MI)
Returns whether the instruction is in H form (16 bit operands)
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, Register DstReg, ArrayRef< MachineOperand > Cond, Register TrueReg, Register FalseReg) const override
static bool hasBTISemantics(const MachineInstr &MI)
Returns whether the instruction can be compatible with non-zero BTYPE.
static bool isQForm(const MachineInstr &MI)
Returns whether the instruction is in Q form (128 bit operands)
static bool getMemOpInfo(unsigned Opcode, TypeSize &Scale, TypeSize &Width, int64_t &MinOffset, int64_t &MaxOffset)
Returns true if opcode Opc is a memory operation.
static bool isTailCallReturnInst(const MachineInstr &MI)
Returns true if MI is one of the TCRETURN* instructions.
static bool isFPRCopy(const MachineInstr &MI)
Does this instruction rename an FPR without modifying bits?
MachineInstr * emitLdStWithAddr(MachineInstr &MemI, const ExtAddrMode &AM) const override
std::optional< DestSourcePair > isCopyInstrImpl(const MachineInstr &MI) const override
If the specific machine instruction is an instruction that moves/copies value from one register to an...
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
GetInstSize - Return the number of bytes of code the specified instruction may be.
static bool isZExtLoad(const MachineInstr &MI)
Returns whether the instruction is a zero-extending load.
bool areMemAccessesTriviallyDisjoint(const MachineInstr &MIa, const MachineInstr &MIb) const override
void copyPhysRegImpl(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, Register DestReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
static bool isGPRCopy(const MachineInstr &MI)
Does this instruction rename a GPR without modifying bits?
static unsigned convertToFlagSettingOpc(unsigned Opc)
Return the opcode that set flags when possible.
void createPauthEpilogueInstr(MachineBasicBlock &MBB, DebugLoc DL) const
Return true when there is potentially a faster code sequence for an instruction chain ending in Root.
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
bool canInsertSelect(const MachineBasicBlock &, ArrayRef< MachineOperand > Cond, Register, Register, Register, int &, int &, int &) const override
Register isLoadFromStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override
Check for post-frame ptr elimination stack locations as well.
static const MachineOperand & getLdStOffsetOp(const MachineInstr &MI)
Returns the immediate offset operator of a load/store.
bool isCoalescableExtInstr(const MachineInstr &MI, Register &SrcReg, Register &DstReg, unsigned &SubIdx) const override
static std::optional< unsigned > getUnscaledLdSt(unsigned Opc)
Returns the unscaled load/store for the scaled load/store opcode, if there is a corresponding unscale...
static bool hasUnscaledLdStOffset(unsigned Opc)
Return true if it has an unscaled load/store offset.
static const MachineOperand & getLdStAmountOp(const MachineInstr &MI)
Returns the shift amount operator of a load/store.
static bool isPreLdSt(const MachineInstr &MI)
Returns whether the instruction is a pre-indexed load/store.
std::optional< ExtAddrMode > getAddrModeFromMemoryOp(const MachineInstr &MemI, const TargetRegisterInfo *TRI) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &MI, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width, const TargetRegisterInfo *TRI) const override
bool analyzeBranchPredicate(MachineBasicBlock &MBB, MachineBranchPredicate &MBP, bool AllowModify) const override
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isPairableLdStInst(const MachineInstr &MI)
Return true if pairing the given load or store may be paired with another.
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
static bool isSExtLoad(const MachineInstr &MI)
Returns whether the instruction is a sign-extending load.
const AArch64RegisterInfo & getRegisterInfo() const
getRegisterInfo - TargetInstrInfo is a superset of MRegister info.
static bool isPreSt(const MachineInstr &MI)
Returns whether the instruction is a pre-indexed store.
void insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const override
AArch64InstrInfo(const AArch64Subtarget &STI)
static bool isPairedLdSt(const MachineInstr &MI)
Returns whether the instruction is a paired load/store.
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
bool getMemOperandWithOffsetWidth(const MachineInstr &MI, const MachineOperand *&BaseOp, int64_t &Offset, bool &OffsetIsScalable, TypeSize &Width, const TargetRegisterInfo *TRI) const
If OffsetIsScalable is set to 'true', the offset is scaled by vscale.
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
static bool isStridedAccess(const MachineInstr &MI)
Return true if the given load or store is a strided memory access.
bool shouldClusterMemOps(ArrayRef< const MachineOperand * > BaseOps1, int64_t Offset1, bool OffsetIsScalable1, ArrayRef< const MachineOperand * > BaseOps2, int64_t Offset2, bool OffsetIsScalable2, unsigned ClusterSize, unsigned NumBytes) const override
Detect opportunities for ldp/stp formation.
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
bool isThroughputPattern(unsigned Pattern) const override
Return true when a code sequence can improve throughput.
MachineOperand & getMemOpBaseRegImmOfsOffsetOperand(MachineInstr &LdSt) const
Return the immediate offset of the base register in a load/store LdSt.
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify=false) const override
bool canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg, const MachineInstr &AddrI, ExtAddrMode &AM) const override
static bool isLdStPairSuppressed(const MachineInstr &MI)
Return true if pairing the given load or store is hinted to be unprofitable.
Register isStoreToStackSlotPostFE(const MachineInstr &MI, int &FrameIndex) const override
Check for post-frame ptr elimination stack locations as well.
std::unique_ptr< TargetInstrInfo::PipelinerLoopInfo > analyzeLoopForPipelining(MachineBasicBlock *LoopBB) const override
void copyPhysRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, llvm::ArrayRef< unsigned > Indices) const
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &DL, int *BytesAdded=nullptr) const override
AArch64CC::CondCode insertCmpForCondBr(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const DebugLoc &DL, ArrayRef< MachineOperand > Cond) const
Inserts the compare instruction needed to un-fuse a fused conditional branch instruction and returns ...
bool optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask, int64_t CmpValue, const MachineRegisterInfo *MRI) const override
optimizeCompareInstr - Convert the instruction supplying the argument to the comparison into one that...
static unsigned getLoadStoreImmIdx(unsigned Opc)
Returns the index for the immediate for a given instruction.
static bool isGPRZero(const MachineInstr &MI)
Does this instruction set its full destination register to zero?
void copyGPRRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, MCRegister DestReg, MCRegister SrcReg, bool KillSrc, unsigned Opcode, unsigned ZeroReg, llvm::ArrayRef< unsigned > Indices) const
bool analyzeCompare(const MachineInstr &MI, Register &SrcReg, Register &SrcReg2, int64_t &CmpMask, int64_t &CmpValue) const override
analyzeCompare - For a comparison instruction, return the source registers in SrcReg and SrcReg2,...
CombinerObjective getCombinerObjective(unsigned Pattern) const override
static bool isFpOrNEON(Register Reg)
Returns whether the physical register is FP or NEON.
bool isAsCheapAsAMove(const MachineInstr &MI) const override
std::optional< DestSourcePair > isCopyLikeInstrImpl(const MachineInstr &MI) const override
static void suppressLdStPair(MachineInstr &MI)
Hint that pairing the given load or store is unprofitable.
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
static bool isPreLd(const MachineInstr &MI)
Returns whether the instruction is a pre-indexed load.
bool optimizeCondBranch(MachineInstr &MI) const override
Replace csincr-branch sequence by simple conditional branch.
static int getMemScale(unsigned Opc)
Scaling factor for (scaled or unscaled) load or store.
bool isCandidateToMergeOrPair(const MachineInstr &MI) const
Return true if this is a load/store that can be potentially paired/merged.
MCInst getNop() const override
static const MachineOperand & getLdStBaseOp(const MachineInstr &MI)
Returns the base register operator of a load/store.
bool isReservedReg(const MachineFunction &MF, MCRegister Reg) const
const AArch64RegisterInfo * getRegisterInfo() const override
bool isNeonAvailable() const
Returns true if the target has NEON and the function at runtime is known to have NEON enabled (e....
bool isSVEorStreamingSVEAvailable() const
Returns true if the target has access to either the full range of SVE instructions,...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
const T & front() const
Get the first element.
Definition ArrayRef.h:144
size_t size() const
Get the array size.
Definition ArrayRef.h:141
This is an important base class in LLVM.
Definition Constant.h:43
A debug info location.
Definition DebugLoc.h:126
bool empty() const
Definition DenseMap.h:206
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:319
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
Definition Function.h:699
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
Definition Function.h:696
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
A set of register units used to track register liveness.
bool available(MCRegister Reg) const
Returns true if no part of physical register Reg is live.
LLVM_ABI void accumulate(const MachineInstr &MI)
Adds all register units used, defined or clobbered in MI.
static LocationSize precise(uint64_t Value)
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition MCAsmInfo.h:67
bool usesWindowsCFI() const
Definition MCAsmInfo.h:675
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it.
Definition MCDwarf.h:628
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
Definition MCDwarf.h:670
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
Definition MCDwarf.h:643
static MCCFIInstruction createEscape(MCSymbol *L, StringRef Vals, SMLoc Loc={}, StringRef Comment="")
.cfi_escape Allows the user to add arbitrary bytes to the unwind info.
Definition MCDwarf.h:756
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
Describe properties that are true of each instruction in the target description file.
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
ArrayRef< MCOperandInfo > operands() const
bool hasSuperClassEq(const MCRegisterClass *RC) const
Returns true if RC is a super-class of or equal to this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
bool hasSubClassEq(const MCRegisterClass *RC) const
Returns true if RC is a sub-class of or equal to this class.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
constexpr bool isValid() const
Definition MCRegister.h:84
static constexpr unsigned NoRegister
Definition MCRegister.h:60
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1579
Set of metadata that should be preserved when using BuildMI().
bool isInlineAsmBrIndirectTarget() const
Returns true if this is the indirect dest of an INLINEASM_BR.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
reverse_instr_iterator instr_rbegin()
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
reverse_instr_iterator instr_rend()
Instructions::iterator instr_iterator
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator insertAfter(iterator I, MachineInstr *MI)
Insert MI into the instruction list after I.
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
void setMachineBlockAddressTaken()
Set this block to indicate that its address is used as something other than the target of a terminato...
LLVM_ABI bool isLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll()) const
Return true if the specified register is in the live in set.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
void setStackID(int ObjectIdx, uint8_t ID)
bool isCalleeSavedInfoValid() const
Has the callee saved info been calculated yet?
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
unsigned getNumObjects() const
Return the number of objects.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
unsigned addFrameInst(const MCCFIInstruction &Inst)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineInstr - Allocate a new MachineInstr.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & addUse(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
bool mayLoadOrStore(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read or modify memory.
bool isCopy() const
const MachineBasicBlock * getParent() const
bool isCall(QueryType Type=AnyInBundle) const
bool getFlag(MIFlag Flag) const
Return whether an MI flag is set.
LLVM_ABI uint32_t mergeFlagsWith(const MachineInstr &Other) const
Return the MIFlags which represent both MachineInstrs.
unsigned getNumOperands() const
Retuns the total number of operands.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
LLVM_ABI bool hasUnmodeledSideEffects() const
Return true if this instruction has side effects that are not modeled by mayLoad / mayStore,...
bool registerDefIsDead(Register Reg, const TargetRegisterInfo *TRI) const
Returns true if the register is dead in this machine instruction.
bool definesRegister(Register Reg, const TargetRegisterInfo *TRI) const
Return true if the MachineInstr fully defines the specified register.
LLVM_ABI void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
LLVM_ABI bool hasOrderedMemoryRef() const
Return true if this instruction may have an ordered or volatile memory reference, or if the informati...
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
LLVM_ABI bool isLoadFoldBarrier() const
Returns true if it is illegal to fold a load across this instruction.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
LLVM_ABI void removeOperand(unsigned OpNo)
Erase an operand from an instruction, leaving it with one fewer operand than it started with.
LLVM_ABI void addRegisterDefined(Register Reg, const TargetRegisterInfo *RegInfo=nullptr)
We have determined MI defines a register.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
LLVM_ABI int findRegisterDefOperandIdx(Register Reg, const TargetRegisterInfo *TRI, bool isDead=false, bool Overlap=false) const
Returns the operand index that is a def of the specified register or -1 if it is not found.
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
const std::vector< MachineJumpTableEntry > & getJumpTables() const
A description of a memory reference used in the backend.
@ MOVolatile
The memory access is volatile.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
This class contains meta information specific to a module.
LLVM_ABI MachineFunction * getMachineFunction(const Function &F) const
Returns the MachineFunction associated to IR function F if there is one, otherwise nullptr.
MachineOperand class - Representation of each machine instruction operand.
void setSubReg(unsigned subReg)
unsigned getSubReg() const
void setImm(int64_t immVal)
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
void setIsDead(bool Val=true)
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
void setIsKill(bool Val=true)
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
unsigned getTargetFlags() const
static MachineOperand CreateImm(int64_t Val)
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void setIsUndef(bool Val=true)
Register getReg() const
getReg - Returns the register number.
bool isFI() const
isFI - Tests if this is a MO_FrameIndex operand.
LLVM_ABI bool isIdenticalTo(const MachineOperand &Other) const
Returns true if this operand is identical to the specified operand except for liveness related flags ...
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI bool hasOneNonDBGUse(Register RegNo) const
hasOneNonDBGUse - Return true if there is exactly one non-Debug use of the specified register.
bool tracksLiveness() const
tracksLiveness - Returns true when tracking register liveness accurately.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI void clearKillFlags(Register Reg) const
clearKillFlags - Iterate over all the uses of the given register and clear the kill flag from the Mac...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
bool use_nodbg_empty(Register RegNo) const
use_nodbg_empty - Return true if there are no non-Debug instructions using the specified register.
MachineBasicBlock * getDefBlock(Register Reg) const
Return the machine basic block in which the specified virtual register is defined,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
bool reservedRegsFrozen() const
reservedRegsFrozen - Returns true after freezeReservedRegs() was called to ensure the set of reserved...
use_instr_nodbg_iterator use_instr_nodbg_begin(Register RegNo) const
const TargetRegisterClass * getRegClassOrNull(Register Reg) const
Return the register class of Reg, or null if Reg has not been assigned a register class yet.
LLVM_ABI const TargetRegisterClass * constrainRegClass(Register Reg, const TargetRegisterClass *RC, unsigned MinNumRegs=0)
constrainRegClass - Constrain the register class of the specified virtual register to be a common sub...
LLVM_ABI LLVM_READONLY MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
MI-level patchpoint operands.
Definition StackMaps.h:77
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given patchpoint should emit.
Definition StackMaps.h:105
Wrapper class representing virtual and physical registers.
Definition Register.h:20
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
Definition Register.h:107
constexpr bool isValid() const
Definition Register.h:112
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
static constexpr bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:66
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition Register.h:83
Represents a location in source code.
Definition SMLoc.h:22
bool erase(PtrType Ptr)
Remove pointer from the set.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:134
bool empty() const
Definition SmallSet.h:169
bool erase(const T &V)
Definition SmallSet.h:200
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
void append(StringRef RHS)
Append from a StringRef.
Definition SmallString.h:68
StringRef str() const
Explicit conversion to StringRef.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
MI-level stackmap operands.
Definition StackMaps.h:36
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given stackmap should emit.
Definition StackMaps.h:51
StackOffset holds a fixed and a scalable offset in bytes.
Definition TypeSize.h:30
int64_t getFixed() const
Returns the fixed component of the stack.
Definition TypeSize.h:46
int64_t getScalable() const
Returns the scalable component of the stack.
Definition TypeSize.h:49
static StackOffset get(int64_t Fixed, int64_t Scalable)
Definition TypeSize.h:41
static StackOffset getScalable(int64_t Scalable)
Definition TypeSize.h:40
static StackOffset getFixed(int64_t Fixed)
Definition TypeSize.h:39
MI-level Statepoint operands.
Definition StackMaps.h:159
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given statepoint should emit.
Definition StackMaps.h:208
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Object returned by analyzeLoopForPipelining.
TargetInstrInfo - Interface to description of machine instruction set.
virtual void genAlternativeCodeSequence(MachineInstr &Root, unsigned Pattern, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, DenseMap< Register, unsigned > &InstIdxForVirtReg) const
When getMachineCombinerPatterns() finds patterns, this function generates the instructions that could...
virtual std::optional< ParamLoadedValue > describeLoadedValue(const MachineInstr &MI, Register Reg) const
Produce the expression describing the MI loading a value into the physical register Reg.
virtual bool getMachineCombinerPatterns(MachineInstr &Root, SmallVectorImpl< unsigned > &Patterns, bool DoRegPressureReduce) const
Return true when there is potentially a faster code sequence for an instruction chain ending in Root.
virtual bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const
Test if the given instruction should be considered a scheduling boundary.
virtual CombinerObjective getCombinerObjective(unsigned Pattern) const
Return the objective of a combiner pattern.
virtual bool isFunctionSafeToSplit(const MachineFunction &MF) const
Return true if the function is a viable candidate for machine function splitting.
const Triple & getTargetTriple() const
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
CodeModel::Model getCodeModel() const
Returns the code model.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
bool isOSBinFormatMachO() const
Tests whether the environment is MachO.
Definition Triple.h:875
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:339
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
Definition TypeSize.h:342
Value * getOperand(unsigned i) const
Definition User.h:207
constexpr bool isScalable() const
Returns whether the quantity is scaled by a runtime quantity (vscale).
Definition TypeSize.h:168
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:165
self_iterator getIterator()
Definition ilist_node.h:123
A raw_ostream that writes to an std::string.
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static CondCode getInvertedCondCode(CondCode Code)
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_G1
MO_G1 - A symbol operand with this flag (granule 1) represents the bits 16-31 of a 64-bit address,...
@ MO_S
MO_S - Indicates that the bits of the symbol operand represented by MO_G0 etc are signed.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_GOT
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
@ MO_PREL
MO_PREL - Indicates that the bits of the symbol operand represented by MO_G0 etc are PC relative.
@ MO_G0
MO_G0 - A symbol operand with this flag (granule 0) represents the bits 0-15 of a 64-bit address,...
@ MO_ARM64EC_CALLMANGLE
MO_ARM64EC_CALLMANGLE - Operand refers to the Arm64EC-mangled version of a symbol,...
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ MO_HI12
MO_HI12 - This flag indicates that a symbol operand represents the bits 13-24 of a 64-bit address,...
@ MO_TLS
MO_TLS - Indicates that the operand being accessed is some kind of thread-local symbol.
@ MO_G2
MO_G2 - A symbol operand with this flag (granule 2) represents the bits 32-47 of a 64-bit address,...
@ MO_TAGGED
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
@ MO_G3
MO_G3 - A symbol operand with this flag (granule 3) represents the high 16-bits of a 64-bit address,...
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
unsigned getCheckerSizeInBytes(AuthCheckMethod Method)
Returns the number of bytes added by checkAuthenticatedRegister.
static uint64_t decodeLogicalImmediate(uint64_t val, unsigned regSize)
decodeLogicalImmediate - Decode a logical immediate value in the form "N:immr:imms" (where the immr a...
static unsigned getShiftValue(unsigned Imm)
getShiftValue - Extract the shift value.
static unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET, unsigned Imm)
getArithExtendImm - Encode the extend type and shift amount for an arithmetic instruction: imm: 3-bit...
constexpr bool isLegalArithImmed(const uint64_t C)
isLegalArithImmed -
static unsigned getArithShiftValue(unsigned Imm)
getArithShiftValue - get the arithmetic shift value.
static uint64_t encodeLogicalImmediate(uint64_t imm, unsigned regSize)
encodeLogicalImmediate - Return the encoded immediate value for a logical immediate instruction of th...
static AArch64_AM::ShiftExtendType getExtendType(unsigned Imm)
getExtendType - Extract the extend type for operands of arithmetic ops.
static AArch64_AM::ShiftExtendType getArithExtendType(unsigned Imm)
static AArch64_AM::ShiftExtendType getShiftType(unsigned Imm)
getShiftType - Extract the shift type.
static unsigned getShifterImm(AArch64_AM::ShiftExtendType ST, unsigned Imm)
getShifterImm - Encode the shift type and amount: imm: 6-bit shift amount shifter: 000 ==> lsl 001 ==...
void expandMOVAddr(unsigned Opcode, unsigned TargetFlags, bool IsTargetMachO, SmallVectorImpl< AddrInsnModel > &Insn)
void expandMOVImm(uint64_t Imm, unsigned BitSize, SmallVectorImpl< ImmInsnModel > &Insn)
Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more real move-immediate instructions to...
static const uint64_t InstrFlagIsWhile
static const uint64_t InstrFlagIsPTestLike
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
initializer< Ty > init(const Ty &Val)
constexpr double e
InstrType
Represents how an instruction should be mapped by the outliner.
NodeAddr< InstrNode * > Instr
Definition RDFGraph.h:389
iterator end() const
Definition BasicBlock.h:89
LLVM_ABI Instruction & back() const
LLVM_ABI iterator begin() const
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
@ Offset
Definition DWP.cpp:577
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
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:2570
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
static bool isIndirectBranchOpcode(int Opc)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
unsigned getBLRCallOpcode(const MachineFunction &MF)
Return opcode to be used for indirect calls.
@ AArch64FrameOffsetIsLegal
Offset is legal.
@ AArch64FrameOffsetCanUpdate
Offset can apply, at least partly.
@ AArch64FrameOffsetCannotUpdate
Offset cannot apply.
constexpr bool isPowerOf2_64(uint64_t Value)
Return true if the argument is a power of two > 0 (64 bit edition.)
Definition MathExtras.h:285
Op::Description Desc
unsigned Log2_64(uint64_t Value)
Return the floor log base 2 of the specified value, -1 if the value is zero.
Definition MathExtras.h:332
static bool isSEHInstruction(const MachineInstr &MI)
bool isLFIPrePostMemAccess(unsigned Opcode)
Returns true if Opcode is a pre- or post-indexed memory access that the LFI rewriter expands with a b...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
auto reverse(ContainerTy &&C)
Definition STLExtras.h:408
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:1652
AArch64MachineCombinerPattern
@ MULSUBv8i16_OP2
@ FMULv4i16_indexed_OP1
@ FMLSv1i32_indexed_OP2
@ MULSUBv2i32_indexed_OP1
@ FMLAv2i32_indexed_OP2
@ MULADDv4i16_indexed_OP2
@ FMLAv1i64_indexed_OP1
@ MULSUBv16i8_OP1
@ FMLAv8i16_indexed_OP2
@ FMULv2i32_indexed_OP1
@ MULSUBv8i16_indexed_OP2
@ FMLAv1i64_indexed_OP2
@ MULSUBv4i16_indexed_OP2
@ FMLAv1i32_indexed_OP1
@ FMLAv2i64_indexed_OP2
@ FMLSv8i16_indexed_OP1
@ MULSUBv2i32_OP1
@ FMULv4i16_indexed_OP2
@ MULSUBv4i32_indexed_OP2
@ FMULv2i64_indexed_OP2
@ FMLAv4i32_indexed_OP1
@ MULADDv4i16_OP2
@ FMULv8i16_indexed_OP2
@ MULSUBv4i16_OP1
@ MULADDv4i32_OP2
@ MULADDv2i32_OP2
@ MULADDv16i8_OP2
@ FMLSv4i16_indexed_OP1
@ MULADDv16i8_OP1
@ FMLAv2i64_indexed_OP1
@ FMLAv1i32_indexed_OP2
@ FMLSv2i64_indexed_OP2
@ MULADDv2i32_OP1
@ MULADDv4i32_OP1
@ MULADDv2i32_indexed_OP1
@ MULSUBv16i8_OP2
@ MULADDv4i32_indexed_OP1
@ MULADDv2i32_indexed_OP2
@ FMLAv4i16_indexed_OP2
@ MULSUBv8i16_OP1
@ FMULv2i32_indexed_OP2
@ FMLSv2i32_indexed_OP2
@ FMLSv4i32_indexed_OP1
@ FMULv2i64_indexed_OP1
@ MULSUBv4i16_OP2
@ FMLSv4i16_indexed_OP2
@ FMLAv2i32_indexed_OP1
@ FMLSv2i32_indexed_OP1
@ FMLAv8i16_indexed_OP1
@ MULSUBv4i16_indexed_OP1
@ FMLSv4i32_indexed_OP2
@ MULADDv4i32_indexed_OP2
@ MULSUBv4i32_OP2
@ MULSUBv8i16_indexed_OP1
@ MULADDv8i16_OP2
@ MULSUBv2i32_indexed_OP2
@ FMULv4i32_indexed_OP2
@ FMLSv2i64_indexed_OP1
@ MULADDv4i16_OP1
@ FMLAv4i32_indexed_OP2
@ MULADDv8i16_indexed_OP1
@ FMULv4i32_indexed_OP1
@ FMLAv4i16_indexed_OP1
@ FMULv8i16_indexed_OP1
@ MULADDv8i16_OP1
@ MULSUBv4i32_indexed_OP1
@ MULSUBv4i32_OP1
@ FMLSv8i16_indexed_OP2
@ MULADDv8i16_indexed_OP2
@ MULSUBv2i32_OP2
@ FMLSv1i64_indexed_OP2
@ MULADDv4i16_indexed_OP1
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
void emitFrameOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, StackOffset Offset, const TargetInstrInfo *TII, MachineInstr::MIFlag=MachineInstr::NoFlags, bool SetNZCV=false, bool NeedsWinCFI=false, bool *HasWinCFI=nullptr, bool EmitCFAOffset=false, StackOffset InitialOffset={}, unsigned FrameReg=AArch64::SP)
emitFrameOffset - Emit instructions as needed to set DestReg to SrcReg plus Offset.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1769
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:227
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:323
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:2208
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:1963
static const MachineMemOperand::Flags MOSuppressPair
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:567
void appendLEB128(SmallVectorImpl< U > &Buffer, T Value)
Definition LEB128.h:280
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.