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"
55#include "llvm/Support/LEB128.h"
59#include <cassert>
60#include <cstdint>
61#include <iterator>
62#include <utility>
63
64using namespace llvm;
65
66#define GET_INSTRINFO_CTOR_DTOR
67#include "AArch64GenInstrInfo.inc"
68
69#define DEBUG_TYPE "AArch64InstrInfo"
70
71STATISTIC(NumCopyInstrs, "Number of COPY instructions expanded");
72STATISTIC(NumZCRegMoveInstrsGPR, "Number of zero-cycle GPR register move "
73 "instructions expanded from canonical COPY");
74STATISTIC(NumZCRegMoveInstrsFPR, "Number of zero-cycle FPR register move "
75 "instructions expanded from canonical COPY");
76STATISTIC(NumZCZeroingInstrsGPR, "Number of zero-cycle GPR zeroing "
77 "instructions expanded from canonical COPY");
78// NumZCZeroingInstrsFPR is counted at AArch64AsmPrinter
79
81 : AArch64GenInstrInfo(STI, RI, AArch64::ADJCALLSTACKDOWN,
82 AArch64::ADJCALLSTACKUP, AArch64::CATCHRET),
83 RI(STI.getTargetTriple(), STI.getHwMode()), Subtarget(STI) {}
84
85/// Return the maximum number of bytes of code the specified instruction may be
86/// after LFI rewriting. If the instruction is not rewritten, std::nullopt is
87/// returned (use default sizing).
88///
89/// NOTE: the size estimates here must be kept in sync with the rewrites in
90/// AArch64MCLFIRewriter.cpp. Sizes may be overestimates of the rewritten
91/// instruction sequences.
92static std::optional<unsigned> getLFIInstSizeInBytes(const MachineInstr &MI) {
93 switch (MI.getOpcode()) {
94 case AArch64::SVC:
95 // SVC expands to 4 instructions.
96 return 16;
97 case AArch64::BR:
98 case AArch64::BLR:
99 // Indirect branches/calls expand to 2 instructions (guard + br/blr).
100 return 8;
101 case AArch64::RET:
102 // RET through another register expands to 2 instructions (guard + ret).
103 // RET through LR may also expand to 2 instructions if a deferred LR guard
104 // is flushed before the return.
105 return 8;
106 case AArch64::RETAA:
107 case AArch64::RETAB:
108 // Authenticated returns expand to 3 instructions (authenticate + guard +
109 // ret).
110 return 12;
111 case AArch64::BRAA:
112 case AArch64::BRAAZ:
113 case AArch64::BRAB:
114 case AArch64::BRABZ:
115 case AArch64::BLRAA:
116 case AArch64::BLRAAZ:
117 case AArch64::BLRAB:
118 case AArch64::BLRABZ:
119 // Authenticated branches/calls expand to 3 instructions (authenticate +
120 // guard + branch).
121 return 12;
122 case AArch64::AUTIASP:
123 case AArch64::AUTIBSP:
124 case AArch64::AUTIAZ:
125 case AArch64::AUTIBZ:
126 case AArch64::XPACLRI:
127 // Authenticating LR expands to the instruction plus a deferred LR guard.
128 return 8;
129 case AArch64::SYSxt:
130 // VA-based DC/IC ops (op1=3, Cn=7, op2=1) expand to 2 instructions.
131 if (MI.getOperand(0).getImm() == 3 && MI.getOperand(1).getImm() == 7 &&
132 MI.getOperand(3).getImm() == 1)
133 return 8;
134 return std::nullopt;
135 default:
136 break;
137 }
138
139 // Detect instructions that explicitly define SP or LR.
140 bool ModifiesLR = false;
141 bool ModifiesSP = false;
142 for (const MachineOperand &MO : MI.defs()) {
143 if (!MO.isReg())
144 continue;
145 if (MO.getReg() == AArch64::LR)
146 ModifiesLR = true;
147 else if (MO.getReg() == AArch64::SP)
148 ModifiesSP = true;
149 }
150
151 // Memory accesses expand to a base-register guard plus the rewritten access
152 // (8 bytes), with an extra base-register update for pre/post-index forms (12
153 // bytes total). If the access also defines LR, an LR mask is appended (+4
154 // bytes). Depending on additional optimizations that the rewriter performs,
155 // this may be an overestimate.
156 if (MI.mayLoadOrStore()) {
157 unsigned Size = isLFIPrePostMemAccess(MI.getOpcode()) ? 12 : 8;
158 if (ModifiesLR)
159 Size += 4;
160 return Size;
161 }
162
163 // Non memory operations that modify LR or SP expand to 2 instructions.
164 if (ModifiesSP || ModifiesLR)
165 return 8;
166
167 // Default case: instructions that don't cause expansion.
168 // - TP accesses in LFI are a single load/store, so no expansion.
169 // - All remaining instructions are not rewritten.
170 return std::nullopt;
171}
172
173/// GetInstSize - Return the number of bytes of code the specified
174/// instruction may be. This returns the maximum number of bytes.
176 const MCInstrDesc &Desc = MI.getDesc();
177 if (!Desc.isPseudo() && !Subtarget.isLFI()) {
178 assert(Desc.getSize() == 4 && "Unexpected instruction size");
179 return 4;
180 }
181
182 const MachineBasicBlock &MBB = *MI.getParent();
183 const MachineFunction *MF = MBB.getParent();
184 const Function &F = MF->getFunction();
185 const MCAsmInfo &MAI = MF->getTarget().getMCAsmInfo();
186
187 {
188 auto Op = MI.getOpcode();
189 if (Op == AArch64::INLINEASM || Op == AArch64::INLINEASM_BR)
190 return getInlineAsmLength(MI.getOperand(0).getSymbolName(), MAI);
191 }
192
193 // Meta-instructions emit no code.
194 if (MI.isMetaInstruction())
195 return 0;
196
197 // FIXME: We currently only handle pseudoinstructions that don't get expanded
198 // before the assembly printer.
199 unsigned NumBytes = 0;
200
201 // LFI rewriter expansions that supersede normal sizing.
202 const auto &STI = MF->getSubtarget<AArch64Subtarget>();
203 if (STI.isLFI())
204 if (auto Size = getLFIInstSizeInBytes(MI))
205 return *Size;
206
207 if (!MI.isBundle() && isTailCallReturnInst(MI)) {
208 NumBytes = Desc.getSize() ? Desc.getSize() : 4;
209
210 const auto *MFI = MF->getInfo<AArch64FunctionInfo>();
211 if (!MFI->shouldSignReturnAddress(*MF))
212 return NumBytes;
213
214 auto Method = STI.getAuthenticatedLRCheckMethod(*MF);
215 NumBytes += AArch64PAuth::getCheckerSizeInBytes(Method);
216 return NumBytes;
217 }
218
219 // Size should be preferably set in
220 // llvm/lib/Target/AArch64/AArch64InstrInfo.td (default case).
221 // Specific cases handle instructions of variable sizes
222 switch (Desc.getOpcode()) {
223 default:
224 if (Desc.getSize())
225 return Desc.getSize();
226
227 // Anything not explicitly designated otherwise (i.e. pseudo-instructions
228 // with fixed constant size but not specified in .td file) is a normal
229 // 4-byte insn.
230 NumBytes = 4;
231 break;
232 case TargetOpcode::STACKMAP:
233 // The upper bound for a stackmap intrinsic is the full length of its shadow
234 NumBytes = StackMapOpers(&MI).getNumPatchBytes();
235 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
236 break;
237 case TargetOpcode::PATCHPOINT:
238 // The size of the patchpoint intrinsic is the number of bytes requested
239 NumBytes = PatchPointOpers(&MI).getNumPatchBytes();
240 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
241 break;
242 case TargetOpcode::STATEPOINT:
243 NumBytes = StatepointOpers(&MI).getNumPatchBytes();
244 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
245 // No patch bytes means a normal call inst is emitted
246 if (NumBytes == 0)
247 NumBytes = 4;
248 break;
249 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
250 // If `patchable-function-entry` is set, PATCHABLE_FUNCTION_ENTER
251 // instructions are expanded to the specified number of NOPs. Otherwise,
252 // they are expanded to 36-byte XRay sleds.
253 NumBytes =
254 F.getFnAttributeAsParsedInteger("patchable-function-entry", 9) * 4;
255 break;
256 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
257 case TargetOpcode::PATCHABLE_TAIL_CALL:
258 case TargetOpcode::PATCHABLE_TYPED_EVENT_CALL:
259 // An XRay sled can be 4 bytes of alignment plus a 32-byte block.
260 NumBytes = 36;
261 break;
262 case TargetOpcode::PATCHABLE_EVENT_CALL:
263 // EVENT_CALL XRay sleds are exactly 6 instructions long (no alignment).
264 NumBytes = 24;
265 break;
266
267 case AArch64::SPACE:
268 NumBytes = MI.getOperand(1).getImm();
269 break;
270 case AArch64::MOVaddr:
271 case AArch64::MOVaddrJT:
272 case AArch64::MOVaddrCP:
273 case AArch64::MOVaddrBA:
274 case AArch64::MOVaddrTLS:
275 case AArch64::MOVaddrEXT: {
276 // Use the same logic as the pseudo expansion to count instructions.
279 MI.getOperand(1).getTargetFlags(),
280 Subtarget.isTargetMachO(), Insn);
281 NumBytes = Insn.size() * 4;
282 break;
283 }
284
285 case AArch64::MOVi32imm:
286 case AArch64::MOVi64imm: {
287 // Use the same logic as the pseudo expansion to count instructions.
288 unsigned BitSize = Desc.getOpcode() == AArch64::MOVi32imm ? 32 : 64;
290 AArch64_IMM::expandMOVImm(MI.getOperand(1).getImm(), BitSize, Insn);
291 NumBytes = Insn.size() * 4;
292 break;
293 }
294
295 case TargetOpcode::BUNDLE:
296 NumBytes = getInstBundleSize(MI);
297 break;
298 }
299
300 return NumBytes;
301}
302
305 // Block ends with fall-through condbranch.
306 switch (LastInst->getOpcode()) {
307 default:
308 llvm_unreachable("Unknown branch instruction?");
309 case AArch64::Bcc:
310 Target = LastInst->getOperand(1).getMBB();
311 Cond.push_back(LastInst->getOperand(0));
312 break;
313 case AArch64::CBZW:
314 case AArch64::CBZX:
315 case AArch64::CBNZW:
316 case AArch64::CBNZX:
317 Target = LastInst->getOperand(1).getMBB();
318 Cond.push_back(MachineOperand::CreateImm(-1));
319 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
320 Cond.push_back(LastInst->getOperand(0));
321 break;
322 case AArch64::TBZW:
323 case AArch64::TBZX:
324 case AArch64::TBNZW:
325 case AArch64::TBNZX:
326 Target = LastInst->getOperand(2).getMBB();
327 Cond.push_back(MachineOperand::CreateImm(-1));
328 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
329 Cond.push_back(LastInst->getOperand(0));
330 Cond.push_back(LastInst->getOperand(1));
331 break;
332 case AArch64::CBWPri:
333 case AArch64::CBXPri:
334 case AArch64::CBWPrr:
335 case AArch64::CBXPrr:
336 Target = LastInst->getOperand(3).getMBB();
337 Cond.push_back(MachineOperand::CreateImm(-1));
338 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode()));
339 Cond.push_back(LastInst->getOperand(0));
340 Cond.push_back(LastInst->getOperand(1));
341 Cond.push_back(LastInst->getOperand(2));
342 break;
343 case AArch64::CBBAssertExt:
344 case AArch64::CBHAssertExt:
345 Target = LastInst->getOperand(3).getMBB();
346 Cond.push_back(MachineOperand::CreateImm(-1)); // -1
347 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); // Opc
348 Cond.push_back(LastInst->getOperand(0)); // Cond
349 Cond.push_back(LastInst->getOperand(1)); // Op0
350 Cond.push_back(LastInst->getOperand(2)); // Op1
351 Cond.push_back(LastInst->getOperand(4)); // Ext0
352 Cond.push_back(LastInst->getOperand(5)); // Ext1
353 break;
354 }
355}
356
357static unsigned getBranchDisplacementBits(const AArch64Options &CLOpts,
358 unsigned Opc) {
359 switch (Opc) {
360 default:
361 llvm_unreachable("unexpected opcode!");
362 case AArch64::B:
363 return CLOpts.b_offset_bits;
364 case AArch64::TBNZW:
365 case AArch64::TBZW:
366 case AArch64::TBNZX:
367 case AArch64::TBZX:
368 return CLOpts.tbz_offset_bits;
369 case AArch64::CBNZW:
370 case AArch64::CBZW:
371 case AArch64::CBNZX:
372 case AArch64::CBZX:
373 return CLOpts.cbz_offset_bits;
374 case AArch64::Bcc:
375 return CLOpts.bcc_offset_bits;
376 case AArch64::CBWPri:
377 case AArch64::CBXPri:
378 case AArch64::CBBAssertExt:
379 case AArch64::CBHAssertExt:
380 case AArch64::CBWPrr:
381 case AArch64::CBXPrr:
382 return CLOpts.cb_offset_bits;
383 }
384}
385
387 int64_t BrOffset) const {
388 unsigned Bits = getBranchDisplacementBits(Subtarget.getCLOpts(), BranchOp);
389 assert(Bits >= 3 && "max branch displacement must be enough to jump"
390 "over conditional branch expansion");
391 return isIntN(Bits, BrOffset / 4);
392}
393
396 switch (MI.getOpcode()) {
397 default:
398 llvm_unreachable("unexpected opcode!");
399 case AArch64::B:
400 return MI.getOperand(0).getMBB();
401 case AArch64::TBZW:
402 case AArch64::TBNZW:
403 case AArch64::TBZX:
404 case AArch64::TBNZX:
405 return MI.getOperand(2).getMBB();
406 case AArch64::CBZW:
407 case AArch64::CBNZW:
408 case AArch64::CBZX:
409 case AArch64::CBNZX:
410 case AArch64::Bcc:
411 return MI.getOperand(1).getMBB();
412 case AArch64::CBWPri:
413 case AArch64::CBXPri:
414 case AArch64::CBBAssertExt:
415 case AArch64::CBHAssertExt:
416 case AArch64::CBWPrr:
417 case AArch64::CBXPrr:
418 return MI.getOperand(3).getMBB();
419 }
420}
421
423 MachineBasicBlock &NewDestBB,
424 MachineBasicBlock &RestoreBB,
425 const DebugLoc &DL,
426 int64_t BrOffset,
427 RegScavenger *RS) const {
428 assert(RS && "RegScavenger required for long branching");
429 assert(MBB.empty() &&
430 "new block should be inserted for expanding unconditional branch");
431 assert(MBB.pred_size() == 1);
432 assert(RestoreBB.empty() &&
433 "restore block should be inserted for restoring clobbered registers");
434
435 auto buildIndirectBranch = [&](Register Reg, MachineBasicBlock &DestBB) {
436 // Offsets outside of the signed 33-bit range are not supported for ADRP +
437 // ADD.
438 if (!isInt<33>(BrOffset))
440 "Branch offsets outside of the signed 33-bit range not supported");
441
442 BuildMI(MBB, MBB.end(), DL, get(AArch64::ADRP), Reg)
443 .addSym(DestBB.getSymbol(), AArch64II::MO_PAGE);
444 BuildMI(MBB, MBB.end(), DL, get(AArch64::ADDXri), Reg)
445 .addReg(Reg)
446 .addSym(DestBB.getSymbol(), AArch64II::MO_PAGEOFF | AArch64II::MO_NC)
447 .addImm(0);
448 BuildMI(MBB, MBB.end(), DL, get(AArch64::BR)).addReg(Reg);
449 };
450
451 RS->enterBasicBlockEnd(MBB);
452 // If X16 is unused, we can rely on the linker to insert a range extension
453 // thunk if NewDestBB is out of range of a single B instruction.
454 constexpr Register Reg = AArch64::X16;
455 if (!RS->isRegUsed(Reg)) {
456 insertUnconditionalBranch(MBB, &NewDestBB, DL);
457 RS->setRegUsed(Reg);
458 return;
459 }
460
461 // In a cold block without BTI, insert the indirect branch if a register is
462 // free. Skip this if BTI is enabled to avoid inserting a BTI at the target,
463 // prioritizing a dynamic cost in cold code over a static cost in hot code.
464 AArch64FunctionInfo *AFI = MBB.getParent()->getInfo<AArch64FunctionInfo>();
465 bool HasBTI = AFI && AFI->branchTargetEnforcement();
466 if (MBB.getSectionID() == MBBSectionID::ColdSectionID && !HasBTI) {
467 Register Scavenged = RS->FindUnusedReg(&AArch64::GPR64RegClass);
468 if (Scavenged.isValid()) {
469 buildIndirectBranch(Scavenged, NewDestBB);
470 RS->setRegUsed(Scavenged);
471 return;
472 }
473 }
474
475 // Note: Spilling X16 briefly moves the stack pointer, making it incompatible
476 // with red zones.
477 if (!AFI || AFI->hasRedZone().value_or(true))
479 "Unable to insert indirect branch inside function that has red zone");
480
481 // Otherwise, spill X16 and defer range extension to the linker.
482 BuildMI(MBB, MBB.end(), DL, get(AArch64::STRXpre))
483 .addReg(AArch64::SP, RegState::Define)
484 .addReg(Reg)
485 .addReg(AArch64::SP)
486 .addImm(-16);
487
488 BuildMI(MBB, MBB.end(), DL, get(AArch64::B)).addMBB(&RestoreBB);
489
490 BuildMI(RestoreBB, RestoreBB.end(), DL, get(AArch64::LDRXpost))
491 .addReg(AArch64::SP, RegState::Define)
493 .addReg(AArch64::SP)
494 .addImm(16);
495}
496
497// Branch analysis.
500 MachineBasicBlock *&FBB,
502 bool AllowModify) const {
503 // If the block has no terminators, it just falls into the block after it.
504 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
505 if (I == MBB.end())
506 return false;
507
508 // Skip over SpeculationBarrierEndBB terminators
509 if (I->getOpcode() == AArch64::SpeculationBarrierISBDSBEndBB ||
510 I->getOpcode() == AArch64::SpeculationBarrierSBEndBB) {
511 --I;
512 }
513
514 if (!isUnpredicatedTerminator(*I))
515 return false;
516
517 // Get the last instruction in the block.
518 MachineInstr *LastInst = &*I;
519
520 // If there is only one terminator instruction, process it.
521 unsigned LastOpc = LastInst->getOpcode();
522 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
523 if (isUncondBranchOpcode(LastOpc)) {
524 TBB = LastInst->getOperand(0).getMBB();
525 return false;
526 }
527 if (isCondBranchOpcode(LastOpc)) {
528 // Block ends with fall-through condbranch.
529 parseCondBranch(LastInst, TBB, Cond);
530 return false;
531 }
532 return true; // Can't handle indirect branch.
533 }
534
535 // Get the instruction before it if it is a terminator.
536 MachineInstr *SecondLastInst = &*I;
537 unsigned SecondLastOpc = SecondLastInst->getOpcode();
538
539 // If AllowModify is true and the block ends with two or more unconditional
540 // branches, delete all but the first unconditional branch.
541 if (AllowModify && isUncondBranchOpcode(LastOpc)) {
542 while (isUncondBranchOpcode(SecondLastOpc)) {
543 LastInst->eraseFromParent();
544 LastInst = SecondLastInst;
545 LastOpc = LastInst->getOpcode();
546 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
547 // Return now the only terminator is an unconditional branch.
548 TBB = LastInst->getOperand(0).getMBB();
549 return false;
550 }
551 SecondLastInst = &*I;
552 SecondLastOpc = SecondLastInst->getOpcode();
553 }
554 }
555
556 // If we're allowed to modify and the block ends in a unconditional branch
557 // which could simply fallthrough, remove the branch. (Note: This case only
558 // matters when we can't understand the whole sequence, otherwise it's also
559 // handled by BranchFolding.cpp.)
560 if (AllowModify && isUncondBranchOpcode(LastOpc) &&
561 MBB.isLayoutSuccessor(getBranchDestBlock(*LastInst))) {
562 LastInst->eraseFromParent();
563 LastInst = SecondLastInst;
564 LastOpc = LastInst->getOpcode();
565 if (I == MBB.begin() || !isUnpredicatedTerminator(*--I)) {
566 assert(!isUncondBranchOpcode(LastOpc) &&
567 "unreachable unconditional branches removed above");
568
569 if (isCondBranchOpcode(LastOpc)) {
570 // Block ends with fall-through condbranch.
571 parseCondBranch(LastInst, TBB, Cond);
572 return false;
573 }
574 return true; // Can't handle indirect branch.
575 }
576 SecondLastInst = &*I;
577 SecondLastOpc = SecondLastInst->getOpcode();
578 }
579
580 // If there are three terminators, we don't know what sort of block this is.
581 if (SecondLastInst && I != MBB.begin() && isUnpredicatedTerminator(*--I))
582 return true;
583
584 // If the block ends with a B and a Bcc, handle it.
585 if (isCondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
586 parseCondBranch(SecondLastInst, TBB, Cond);
587 FBB = LastInst->getOperand(0).getMBB();
588 return false;
589 }
590
591 // If the block ends with two unconditional branches, handle it. The second
592 // one is not executed, so remove it.
593 if (isUncondBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
594 TBB = SecondLastInst->getOperand(0).getMBB();
595 I = LastInst;
596 if (AllowModify)
597 I->eraseFromParent();
598 return false;
599 }
600
601 // ...likewise if it ends with an indirect branch followed by an unconditional
602 // branch.
603 if (isIndirectBranchOpcode(SecondLastOpc) && isUncondBranchOpcode(LastOpc)) {
604 I = LastInst;
605 if (AllowModify)
606 I->eraseFromParent();
607 return true;
608 }
609
610 // Otherwise, can't handle this.
611 return true;
612}
613
615 MachineBranchPredicate &MBP,
616 bool AllowModify) const {
617 // Use analyzeBranch to validate the branch pattern.
618 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
620 if (analyzeBranch(MBB, TBB, FBB, Cond, AllowModify))
621 return true;
622
623 // analyzeBranch returns success with empty Cond for unconditional branches.
624 if (Cond.empty())
625 return true;
626
627 MBP.TrueDest = TBB;
628 assert(MBP.TrueDest && "expected!");
629 MBP.FalseDest = FBB ? FBB : MBB.getNextNode();
630
631 MBP.ConditionDef = nullptr;
632 MBP.SingleUseCondition = false;
633
634 // Find the conditional branch. After analyzeBranch succeeds with non-empty
635 // Cond, there's exactly one conditional branch - either last (fallthrough)
636 // or second-to-last (followed by unconditional B).
637 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
638 if (I == MBB.end())
639 return true;
640
641 if (isUncondBranchOpcode(I->getOpcode())) {
642 if (I == MBB.begin())
643 return true;
644 --I;
645 }
646
647 MachineInstr *CondBranch = &*I;
648 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
649
650 switch (CondBranch->getOpcode()) {
651 default:
652 return true;
653
654 case AArch64::Bcc:
655 // Bcc takes the NZCV flag as the operand to branch on, walk up the
656 // instruction stream to find the last instruction to define NZCV.
658 if (MI.modifiesRegister(AArch64::NZCV, /*TRI=*/nullptr)) {
659 MBP.ConditionDef = &MI;
660 break;
661 }
662 }
663 return false;
664
665 case AArch64::CBZW:
666 case AArch64::CBZX:
667 case AArch64::CBNZW:
668 case AArch64::CBNZX: {
669 MBP.LHS = CondBranch->getOperand(0);
670 MBP.RHS = MachineOperand::CreateImm(0);
671 unsigned Opc = CondBranch->getOpcode();
672 MBP.Predicate = (Opc == AArch64::CBNZX || Opc == AArch64::CBNZW)
673 ? MachineBranchPredicate::PRED_NE
674 : MachineBranchPredicate::PRED_EQ;
675 Register CondReg = MBP.LHS.getReg();
676 if (CondReg.isVirtual())
677 MBP.ConditionDef = MRI.getVRegDef(CondReg);
678 return false;
679 }
680
681 case AArch64::TBZW:
682 case AArch64::TBZX:
683 case AArch64::TBNZW:
684 case AArch64::TBNZX: {
685 Register CondReg = CondBranch->getOperand(0).getReg();
686 if (CondReg.isVirtual())
687 MBP.ConditionDef = MRI.getVRegDef(CondReg);
688 return false;
689 }
690 }
691}
692
695 if (Cond[0].getImm() != -1) {
696 // Regular Bcc
699 } else {
700 // Folded compare-and-branch
701 switch (Cond[1].getImm()) {
702 default:
703 llvm_unreachable("Unknown conditional branch!");
704 case AArch64::CBZW:
705 Cond[1].setImm(AArch64::CBNZW);
706 break;
707 case AArch64::CBNZW:
708 Cond[1].setImm(AArch64::CBZW);
709 break;
710 case AArch64::CBZX:
711 Cond[1].setImm(AArch64::CBNZX);
712 break;
713 case AArch64::CBNZX:
714 Cond[1].setImm(AArch64::CBZX);
715 break;
716 case AArch64::TBZW:
717 Cond[1].setImm(AArch64::TBNZW);
718 break;
719 case AArch64::TBNZW:
720 Cond[1].setImm(AArch64::TBZW);
721 break;
722 case AArch64::TBZX:
723 Cond[1].setImm(AArch64::TBNZX);
724 break;
725 case AArch64::TBNZX:
726 Cond[1].setImm(AArch64::TBZX);
727 break;
728
729 // Cond is { -1, Opcode, CC, Op0, Op1, ... }
730 case AArch64::CBWPri:
731 case AArch64::CBXPri:
732 case AArch64::CBBAssertExt:
733 case AArch64::CBHAssertExt:
734 case AArch64::CBWPrr:
735 case AArch64::CBXPrr: {
736 // Pseudos using standard 4bit Arm condition codes
738 static_cast<AArch64CC::CondCode>(Cond[2].getImm());
740 }
741 }
742 }
743
744 return false;
745}
746
748 int *BytesRemoved) const {
749 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
750 if (I == MBB.end())
751 return 0;
752
753 if (!isUncondBranchOpcode(I->getOpcode()) &&
754 !isCondBranchOpcode(I->getOpcode()))
755 return 0;
756
757 // Remove the branch.
758 I->eraseFromParent();
759
760 I = MBB.end();
761
762 if (I == MBB.begin()) {
763 if (BytesRemoved)
764 *BytesRemoved = 4;
765 return 1;
766 }
767 --I;
768 if (!isCondBranchOpcode(I->getOpcode())) {
769 if (BytesRemoved)
770 *BytesRemoved = 4;
771 return 1;
772 }
773
774 // Remove the branch.
775 I->eraseFromParent();
776 if (BytesRemoved)
777 *BytesRemoved = 8;
778
779 return 2;
780}
781
782void AArch64InstrInfo::instantiateCondBranch(
785 if (Cond[0].getImm() != -1) {
786 // Regular Bcc
787 BuildMI(&MBB, DL, get(AArch64::Bcc)).addImm(Cond[0].getImm()).addMBB(TBB);
788 } else {
789 // Folded compare-and-branch
790 // Note that we use addOperand instead of addReg to keep the flags.
791
792 // cbz, cbnz
793 const MachineInstrBuilder MIB =
794 BuildMI(&MBB, DL, get(Cond[1].getImm())).add(Cond[2]);
795
796 // tbz/tbnz
797 if (Cond.size() > 3)
798 MIB.add(Cond[3]);
799
800 // cb
801 if (Cond.size() > 4)
802 MIB.add(Cond[4]);
803
804 MIB.addMBB(TBB);
805
806 // cb[b,h]
807 if (Cond.size() > 5) {
808 MIB.addImm(Cond[5].getImm());
809 MIB.addImm(Cond[6].getImm());
810 }
811 }
812}
813
816 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
817 // Shouldn't be a fall through.
818 assert(TBB && "insertBranch must not be told to insert a fallthrough");
819
820 if (!FBB) {
821 if (Cond.empty()) // Unconditional branch?
822 BuildMI(&MBB, DL, get(AArch64::B)).addMBB(TBB);
823 else
824 instantiateCondBranch(MBB, DL, TBB, Cond);
825
826 if (BytesAdded)
827 *BytesAdded = 4;
828
829 return 1;
830 }
831
832 // Two-way conditional branch.
833 instantiateCondBranch(MBB, DL, TBB, Cond);
834 BuildMI(&MBB, DL, get(AArch64::B)).addMBB(FBB);
835
836 if (BytesAdded)
837 *BytesAdded = 8;
838
839 return 2;
840}
841
842#ifndef NDEBUG
844 switch (Ext) {
845 default:
846 return false;
847 case AArch64_AM::UXTB:
848 case AArch64_AM::SXTB:
849 return Opc == AArch64::CBBAssertExt;
850 case AArch64_AM::UXTH:
851 case AArch64_AM::SXTH:
852 return Opc == AArch64::CBHAssertExt;
853 }
854}
855#endif
856
860 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
861
862 // Parse the condition code, see parseCondBranch() above.
864 switch (Cond.size()) {
865 default:
866 llvm_unreachable("Unknown condition opcode in Cond");
867 case 1: // b.cc
869 break;
870 case 3: { // cbz/cbnz
871 // We must insert a compare against 0.
872 bool Is64Bit;
873 switch (Cond[1].getImm()) {
874 default:
875 llvm_unreachable("Unknown branch opcode in Cond");
876 case AArch64::CBZW:
877 Is64Bit = false;
879 break;
880 case AArch64::CBZX:
881 Is64Bit = true;
883 break;
884 case AArch64::CBNZW:
885 Is64Bit = false;
887 break;
888 case AArch64::CBNZX:
889 Is64Bit = true;
891 break;
892 }
893 Register SrcReg = Cond[2].getReg();
894 if (Is64Bit) {
895 // cmp reg, #0 is actually subs xzr, reg, #0.
896 MRI.constrainRegClass(SrcReg, &AArch64::GPR64spRegClass);
897 BuildMI(MBB, MI, DL, get(AArch64::SUBSXri), AArch64::XZR)
898 .addReg(SrcReg)
899 .addImm(0)
900 .addImm(0);
901 } else {
902 MRI.constrainRegClass(SrcReg, &AArch64::GPR32spRegClass);
903 BuildMI(MBB, MI, DL, get(AArch64::SUBSWri), AArch64::WZR)
904 .addReg(SrcReg)
905 .addImm(0)
906 .addImm(0);
907 }
908 } break;
909 case 4: { // tbz/tbnz
910 // We must insert a tst instruction.
911 switch (Cond[1].getImm()) {
912 default:
913 llvm_unreachable("Unknown branch opcode in Cond");
914 case AArch64::TBZW:
915 case AArch64::TBZX:
917 break;
918 case AArch64::TBNZW:
919 case AArch64::TBNZX:
921 break;
922 }
923 // cmp reg, #foo is actually ands xzr, reg, #1<<foo.
924 if (Cond[1].getImm() == AArch64::TBZW || Cond[1].getImm() == AArch64::TBNZW)
925 BuildMI(MBB, MI, DL, get(AArch64::ANDSWri), AArch64::WZR)
926 .addReg(Cond[2].getReg())
927 .addImm(
929 else
930 BuildMI(MBB, MI, DL, get(AArch64::ANDSXri), AArch64::XZR)
931 .addReg(Cond[2].getReg())
932 .addImm(
934 } break;
935 case 5: { // cb
936 // We must insert a cmp, that is a subs
937 // 0 1 2 3 4
938 // Cond is { -1, Opcode, CC, Op0, Op1 }
939 unsigned SubsOpc, SubsDestReg;
940 bool IsImm = false;
941 CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
942 switch (Cond[1].getImm()) {
943 default:
944 llvm_unreachable("Unknown branch opcode in Cond");
945 case AArch64::CBWPri:
946 SubsOpc = AArch64::SUBSWri;
947 SubsDestReg = AArch64::WZR;
948 IsImm = true;
949 break;
950 case AArch64::CBXPri:
951 SubsOpc = AArch64::SUBSXri;
952 SubsDestReg = AArch64::XZR;
953 IsImm = true;
954 break;
955 case AArch64::CBWPrr:
956 SubsOpc = AArch64::SUBSWrr;
957 SubsDestReg = AArch64::WZR;
958 IsImm = false;
959 break;
960 case AArch64::CBXPrr:
961 SubsOpc = AArch64::SUBSXrr;
962 SubsDestReg = AArch64::XZR;
963 IsImm = false;
964 break;
965 }
966
967 if (IsImm) {
968 MRI.constrainRegClass(Cond[3].getReg(), getRegClass(get(SubsOpc), 1));
969 BuildMI(MBB, MI, DL, get(SubsOpc), SubsDestReg)
970 .addReg(Cond[3].getReg())
971 .addImm(Cond[4].getImm())
972 .addImm(0);
973 } else {
974 MRI.constrainRegClass(Cond[3].getReg(), getRegClass(get(SubsOpc), 1));
975 MRI.constrainRegClass(Cond[4].getReg(), getRegClass(get(SubsOpc), 2));
976 BuildMI(MBB, MI, DL, get(SubsOpc), SubsDestReg)
977 .addReg(Cond[3].getReg())
978 .addReg(Cond[4].getReg());
979 }
980 } break;
981 case 7: { // cb[b,h]
982 // We must insert a cmp, that is a subs, but also zero- or sign-extensions
983 // that have been folded. For the first operand we codegen an explicit
984 // extension, for the second operand we fold the extension into cmp.
985 // 0 1 2 3 4 5 6
986 // Cond is { -1, Opcode, CC, Op0, Op1, Ext0, Ext1 }
987
988 // We need a new register for the now explicitly extended register
989 Register Reg = Cond[3].getReg();
991 unsigned ExtOpc;
992 unsigned ExtBits;
993 AArch64_AM::ShiftExtendType ExtendType =
995 assert(isValidCBExtend(Cond[1].getImm(), ExtendType) &&
996 "Unexpected compare-and-branch instruction for extend type");
997 switch (ExtendType) {
998 default:
999 llvm_unreachable("Unknown shift-extend for CB instruction");
1000 case AArch64_AM::SXTB:
1001 ExtOpc = AArch64::SBFMWri;
1002 ExtBits = AArch64_AM::encodeLogicalImmediate(0xff, 32);
1003 break;
1004 case AArch64_AM::SXTH:
1005 ExtOpc = AArch64::SBFMWri;
1006 ExtBits = AArch64_AM::encodeLogicalImmediate(0xffff, 32);
1007 break;
1008 case AArch64_AM::UXTB:
1009 ExtOpc = AArch64::ANDWri;
1010 ExtBits = AArch64_AM::encodeLogicalImmediate(0xff, 32);
1011 break;
1012 case AArch64_AM::UXTH:
1013 ExtOpc = AArch64::ANDWri;
1014 ExtBits = AArch64_AM::encodeLogicalImmediate(0xffff, 32);
1015 break;
1016 }
1017
1018 // Build the explicit extension of the first operand
1019 Reg = MRI.createVirtualRegister(&AArch64::GPR32commonRegClass);
1021 BuildMI(MBB, MI, DL, get(ExtOpc), Reg).addReg(Cond[3].getReg());
1022 if (ExtOpc != AArch64::ANDWri)
1023 MBBI.addImm(0);
1024 MBBI.addImm(ExtBits);
1025 }
1026
1027 // Now, subs with an extended second operand
1029 MRI.constrainRegClass(Reg, &AArch64::GPR32commonRegClass);
1030 AArch64_AM::ShiftExtendType ExtendType =
1032 assert(isValidCBExtend(Cond[1].getImm(), ExtendType) &&
1033 "Unexpected compare-and-branch instruction for extend type");
1034 BuildMI(MBB, MI, DL, get(AArch64::SUBSWrx), AArch64::WZR)
1035 .addReg(Reg)
1036 .addReg(Cond[4].getReg())
1037 .addImm(AArch64_AM::getArithExtendImm(ExtendType, 0));
1038 } // If no extension is needed, just a regular subs
1039 else {
1040 BuildMI(MBB, MI, DL, get(AArch64::SUBSWrr), AArch64::WZR)
1041 .addReg(Reg)
1042 .addReg(Cond[4].getReg());
1043 }
1044
1045 CC = static_cast<AArch64CC::CondCode>(Cond[2].getImm());
1046 } break;
1047 }
1048 return CC;
1049}
1050
1052 const TargetInstrInfo &TII) {
1053 for (MachineInstr &MI : MBB->terminators()) {
1054 unsigned Opc = MI.getOpcode();
1055 switch (Opc) {
1056 case AArch64::CBZW:
1057 case AArch64::CBZX:
1058 case AArch64::TBZW:
1059 case AArch64::TBZX:
1060 // CBZ/TBZ with WZR/XZR -> unconditional B
1061 if (MI.getOperand(0).getReg() == AArch64::WZR ||
1062 MI.getOperand(0).getReg() == AArch64::XZR) {
1063 DEBUG_WITH_TYPE("optimizeTerminators",
1064 dbgs() << "Removing always taken branch: " << MI);
1065 MachineBasicBlock *Target = TII.getBranchDestBlock(MI);
1066 SmallVector<MachineBasicBlock *> Succs(MBB->successors());
1067 for (auto *S : Succs)
1068 if (S != Target)
1069 MBB->removeSuccessor(S);
1070 DebugLoc DL = MI.getDebugLoc();
1071 while (MBB->rbegin() != &MI)
1072 MBB->rbegin()->eraseFromParent();
1073 MI.eraseFromParent();
1074 BuildMI(MBB, DL, TII.get(AArch64::B)).addMBB(Target);
1075 return true;
1076 }
1077 break;
1078 case AArch64::CBNZW:
1079 case AArch64::CBNZX:
1080 case AArch64::TBNZW:
1081 case AArch64::TBNZX:
1082 // CBNZ/TBNZ with WZR/XZR -> never taken, remove branch and successor
1083 if (MI.getOperand(0).getReg() == AArch64::WZR ||
1084 MI.getOperand(0).getReg() == AArch64::XZR) {
1085 DEBUG_WITH_TYPE("optimizeTerminators",
1086 dbgs() << "Removing never taken branch: " << MI);
1087 MachineBasicBlock *Target = TII.getBranchDestBlock(MI);
1088 MI.getParent()->removeSuccessor(Target);
1089 MI.eraseFromParent();
1090 return true;
1091 }
1092 break;
1093 }
1094 }
1095 return false;
1096}
1097
1098// Find the original register that VReg is copied from.
1099static unsigned removeCopies(const MachineRegisterInfo &MRI, unsigned VReg) {
1100 while (Register::isVirtualRegister(VReg)) {
1101 const MachineInstr *DefMI = MRI.getVRegDef(VReg);
1102 if (!DefMI || !DefMI->isFullCopy())
1103 return VReg;
1104 VReg = DefMI->getOperand(1).getReg();
1105 }
1106 return VReg;
1107}
1108
1109// Determine if VReg is defined by an instruction that can be folded into a
1110// csel instruction. If so, return the folded opcode, and the replacement
1111// register.
1112static unsigned canFoldIntoCSel(const MachineRegisterInfo &MRI, unsigned VReg,
1113 unsigned *NewReg = nullptr) {
1114 VReg = removeCopies(MRI, VReg);
1115 if (!Register::isVirtualRegister(VReg))
1116 return 0;
1117
1118 bool Is64Bit = AArch64::GPR64allRegClass.hasSubClassEq(MRI.getRegClass(VReg));
1119 const MachineInstr *DefMI = MRI.getVRegDef(VReg);
1120 if (!DefMI)
1121 return 0;
1122 unsigned Opc = 0;
1123 unsigned SrcReg = 0;
1124 switch (DefMI->getOpcode()) {
1125 case AArch64::SUBREG_TO_REG:
1126 // Check for the following way to define an 64-bit immediate:
1127 // %0:gpr32 = MOVi32imm 1
1128 // %1:gpr64 = SUBREG_TO_REG %0:gpr32, %subreg.sub_32
1129 if (!DefMI->getOperand(1).isReg())
1130 return 0;
1131 if (!DefMI->getOperand(2).isImm() ||
1132 DefMI->getOperand(2).getImm() != AArch64::sub_32)
1133 return 0;
1134 DefMI = MRI.getVRegDef(DefMI->getOperand(1).getReg());
1135 if (DefMI->getOpcode() != AArch64::MOVi32imm)
1136 return 0;
1137 if (!DefMI->getOperand(1).isImm() || DefMI->getOperand(1).getImm() != 1)
1138 return 0;
1139 assert(Is64Bit);
1140 SrcReg = AArch64::XZR;
1141 Opc = AArch64::CSINCXr;
1142 break;
1143
1144 case AArch64::MOVi32imm:
1145 case AArch64::MOVi64imm:
1146 if (!DefMI->getOperand(1).isImm() || DefMI->getOperand(1).getImm() != 1)
1147 return 0;
1148 SrcReg = Is64Bit ? AArch64::XZR : AArch64::WZR;
1149 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
1150 break;
1151
1152 case AArch64::ADDSXri:
1153 case AArch64::ADDSWri:
1154 // if NZCV is used, do not fold.
1155 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
1156 true) == -1)
1157 return 0;
1158 // fall-through to ADDXri and ADDWri.
1159 [[fallthrough]];
1160 case AArch64::ADDXri:
1161 case AArch64::ADDWri:
1162 // add x, 1 -> csinc.
1163 if (!DefMI->getOperand(2).isImm() || DefMI->getOperand(2).getImm() != 1 ||
1164 DefMI->getOperand(3).getImm() != 0)
1165 return 0;
1166 SrcReg = DefMI->getOperand(1).getReg();
1167 Opc = Is64Bit ? AArch64::CSINCXr : AArch64::CSINCWr;
1168 break;
1169
1170 case AArch64::ORNXrr:
1171 case AArch64::ORNWrr: {
1172 // not x -> csinv, represented as orn dst, xzr, src.
1173 unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
1174 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
1175 return 0;
1176 SrcReg = DefMI->getOperand(2).getReg();
1177 Opc = Is64Bit ? AArch64::CSINVXr : AArch64::CSINVWr;
1178 break;
1179 }
1180
1181 case AArch64::SUBSXrr:
1182 case AArch64::SUBSWrr:
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 SUBXrr and SUBWrr.
1188 [[fallthrough]];
1189 case AArch64::SUBXrr:
1190 case AArch64::SUBWrr: {
1191 // neg x -> csneg, represented as sub dst, xzr, src.
1192 unsigned ZReg = removeCopies(MRI, DefMI->getOperand(1).getReg());
1193 if (ZReg != AArch64::XZR && ZReg != AArch64::WZR)
1194 return 0;
1195 SrcReg = DefMI->getOperand(2).getReg();
1196 Opc = Is64Bit ? AArch64::CSNEGXr : AArch64::CSNEGWr;
1197 break;
1198 }
1199 default:
1200 return 0;
1201 }
1202 assert(Opc && SrcReg && "Missing parameters");
1203
1204 if (NewReg)
1205 *NewReg = SrcReg;
1206 return Opc;
1207}
1208
1211 Register DstReg, Register TrueReg,
1212 Register FalseReg,
1213 SelectExpansion &Exp) const {
1214 // Check register classes.
1215 const MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
1216 const TargetRegisterClass *RC =
1217 RI.getCommonSubClass(MRI.getRegClass(TrueReg), MRI.getRegClass(FalseReg));
1218 if (!RC)
1219 return false;
1220
1221 // Also need to check the dest regclass, in case we're trying to optimize
1222 // something like:
1223 // %1(gpr) = PHI %2(fpr), bb1, %(fpr), bb2
1224 if (!RI.getCommonSubClass(RC, MRI.getRegClass(DstReg)))
1225 return false;
1226
1227 // Expanding cbz/tbz requires a flag setting instruction in addition to the
1228 // select, adding an extra cycle of latency on the condition.
1229 unsigned ExtraCondLat = Cond.size() != 1;
1230 Exp.NumInsts = 1 + ExtraCondLat;
1231 if (ExtraCondLat)
1232 Exp.ClobberedPhysRegs.push_back(AArch64::NZCV);
1233
1234 // GPRs are handled by csel.
1235 // FIXME: Fold in x+1, -x, and ~x when applicable.
1236 if (AArch64::GPR64allRegClass.hasSubClassEq(RC) ||
1237 AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
1238 // Single-cycle csel, csinc, csinv, and csneg.
1239 Exp.CondCycles = 1 + ExtraCondLat;
1240 Exp.TrueCycles = Exp.FalseCycles = 1;
1241 if (canFoldIntoCSel(MRI, TrueReg))
1242 Exp.TrueCycles = 0;
1243 else if (canFoldIntoCSel(MRI, FalseReg))
1244 Exp.FalseCycles = 0;
1245 return true;
1246 }
1247
1248 // Scalar floating point is handled by fcsel.
1249 // FIXME: Form fabs, fmin, and fmax when applicable.
1250 if (AArch64::FPR64RegClass.hasSubClassEq(RC) ||
1251 AArch64::FPR32RegClass.hasSubClassEq(RC)) {
1252 Exp.CondCycles = 5 + ExtraCondLat;
1253 Exp.TrueCycles = Exp.FalseCycles = 2;
1254 return true;
1255 }
1256
1257 // No single conditional move for a 128-bit vector, but we can emit a sequence
1258 // of csetm (~1), dup (~5, cross domain), bsl (~2).
1259 if (AArch64::FPR128RegClass.hasSubClassEq(RC) &&
1260 Subtarget.isNeonAvailable() &&
1261 !MBB.getParent()->getFunction().hasMinSize()) {
1262 Exp.CondCycles = 8 + ExtraCondLat;
1263 Exp.TrueCycles = Exp.FalseCycles = 2;
1264 Exp.NumInsts = 3 + ExtraCondLat;
1265 return true;
1266 }
1267
1268 return false;
1269}
1270
1273 const DebugLoc &DL, Register DstReg,
1275 Register TrueReg, Register FalseReg) const {
1276
1277 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
1279
1280 // A 128-bit vector has no conditional move so blend the operands with a mask
1281 // built from the flags.
1282 if (MRI.constrainRegClass(DstReg, &AArch64::FPR128RegClass)) {
1283 assert(Subtarget.isNeonAvailable() && "Expected NEON for a vector select");
1284 MRI.constrainRegClass(TrueReg, &AArch64::FPR128RegClass);
1285 MRI.constrainRegClass(FalseReg, &AArch64::FPR128RegClass);
1286 Register CondSet = MRI.createVirtualRegister(&AArch64::GPR64RegClass);
1287 BuildMI(MBB, I, DL, get(AArch64::CSINVXr), CondSet)
1288 .addReg(AArch64::XZR)
1289 .addReg(AArch64::XZR)
1291 Register Mask = MRI.createVirtualRegister(&AArch64::FPR128RegClass);
1292 BuildMI(MBB, I, DL, get(AArch64::DUPv2i64gpr), Mask).addReg(CondSet);
1293 BuildMI(MBB, I, DL, get(AArch64::BSPv16i8), DstReg)
1294 .addReg(Mask)
1295 .addReg(TrueReg)
1296 .addReg(FalseReg);
1297 return;
1298 }
1299
1300 unsigned Opc = 0;
1301 const TargetRegisterClass *RC = nullptr;
1302 bool TryFold = false;
1303 if (MRI.constrainRegClass(DstReg, &AArch64::GPR64RegClass)) {
1304 RC = &AArch64::GPR64RegClass;
1305 Opc = AArch64::CSELXr;
1306 TryFold = true;
1307 } else if (MRI.constrainRegClass(DstReg, &AArch64::GPR32RegClass)) {
1308 RC = &AArch64::GPR32RegClass;
1309 Opc = AArch64::CSELWr;
1310 TryFold = true;
1311 } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR64RegClass)) {
1312 RC = &AArch64::FPR64RegClass;
1313 Opc = AArch64::FCSELDrrr;
1314 } else if (MRI.constrainRegClass(DstReg, &AArch64::FPR32RegClass)) {
1315 RC = &AArch64::FPR32RegClass;
1316 Opc = AArch64::FCSELSrrr;
1317 }
1318 assert(RC && "Unsupported regclass");
1319
1320 // Try folding simple instructions into the csel.
1321 if (TryFold) {
1322 unsigned NewReg = 0;
1323 unsigned FoldedOpc = canFoldIntoCSel(MRI, TrueReg, &NewReg);
1324 if (FoldedOpc) {
1325 // The folded opcodes csinc, csinc and csneg apply the operation to
1326 // FalseReg, so we need to invert the condition.
1328 TrueReg = FalseReg;
1329 } else
1330 FoldedOpc = canFoldIntoCSel(MRI, FalseReg, &NewReg);
1331
1332 // Fold the operation. Leave any dead instructions for DCE to clean up.
1333 if (FoldedOpc) {
1334 FalseReg = NewReg;
1335 Opc = FoldedOpc;
1336 // Extend the live range of NewReg.
1337 MRI.clearKillFlags(NewReg);
1338 }
1339 }
1340
1341 // Pull all virtual register into the appropriate class.
1342 MRI.constrainRegClass(TrueReg, RC);
1343 // FalseReg might be WZR or XZR if the folded operand is a literal 1.
1344 assert(
1345 (FalseReg.isVirtual() || FalseReg == AArch64::WZR ||
1346 FalseReg == AArch64::XZR) &&
1347 "FalseReg was folded into a non-virtual register other than WZR or XZR");
1348 if (FalseReg.isVirtual())
1349 MRI.constrainRegClass(FalseReg, RC);
1350
1351 // Insert the csel.
1352 BuildMI(MBB, I, DL, get(Opc), DstReg)
1353 .addReg(TrueReg)
1354 .addReg(FalseReg)
1355 .addImm(CC);
1356}
1357
1358// Return true if Imm can be loaded into a register by a "cheap" sequence of
1359// instructions. For now, "cheap" means at most two instructions.
1360static bool isCheapImmediate(const MachineInstr &MI, unsigned BitSize) {
1361 if (BitSize == 32)
1362 return true;
1363
1364 assert(BitSize == 64 && "Only bit sizes of 32 or 64 allowed");
1365 uint64_t Imm = static_cast<uint64_t>(MI.getOperand(1).getImm());
1367 AArch64_IMM::expandMOVImm(Imm, BitSize, Is);
1368
1369 return Is.size() <= 2;
1370}
1371
1372// Check if a COPY instruction is cheap.
1373static bool isCheapCopy(const MachineInstr &MI, const AArch64RegisterInfo &RI) {
1374 assert(MI.isCopy() && "Expected COPY instruction");
1375 const MachineRegisterInfo &MRI = MI.getMF()->getRegInfo();
1376
1377 // Cross-bank copies (e.g., between GPR and FPR) are expensive on AArch64,
1378 // typically requiring an FMOV instruction with a 2-6 cycle latency.
1379 auto GetRegClass = [&](Register Reg) -> const TargetRegisterClass * {
1380 if (Reg.isVirtual())
1381 return MRI.getRegClass(Reg);
1382 if (Reg.isPhysical())
1383 return RI.getMinimalPhysRegClass(Reg);
1384 return nullptr;
1385 };
1386 const TargetRegisterClass *DstRC = GetRegClass(MI.getOperand(0).getReg());
1387 const TargetRegisterClass *SrcRC = GetRegClass(MI.getOperand(1).getReg());
1388 if (DstRC && SrcRC && !RI.getCommonSubClass(DstRC, SrcRC))
1389 return false;
1390
1391 return MI.isAsCheapAsAMove();
1392}
1393
1394// FIXME: this implementation should be micro-architecture dependent, so a
1395// micro-architecture target hook should be introduced here in future.
1397 if (Subtarget.hasExynosCheapAsMoveHandling()) {
1398 if (isExynosCheapAsMove(MI))
1399 return true;
1400 return MI.isAsCheapAsAMove();
1401 }
1402
1403 switch (MI.getOpcode()) {
1404 default:
1405 return MI.isAsCheapAsAMove();
1406
1407 case TargetOpcode::COPY:
1408 return isCheapCopy(MI, RI);
1409
1410 case AArch64::ADDWrs:
1411 case AArch64::ADDXrs:
1412 case AArch64::SUBWrs:
1413 case AArch64::SUBXrs:
1414 return Subtarget.hasALULSLFast() && MI.getOperand(3).getImm() <= 4;
1415
1416 // If MOVi32imm or MOVi64imm can be expanded into ORRWri or
1417 // ORRXri, it is as cheap as MOV.
1418 // Likewise if it can be expanded to MOVZ/MOVN/MOVK.
1419 case AArch64::MOVi32imm:
1420 return isCheapImmediate(MI, 32);
1421 case AArch64::MOVi64imm:
1422 return isCheapImmediate(MI, 64);
1423 }
1424}
1425
1426bool AArch64InstrInfo::isFalkorShiftExtFast(const MachineInstr &MI) {
1427 switch (MI.getOpcode()) {
1428 default:
1429 return false;
1430
1431 case AArch64::ADDWrs:
1432 case AArch64::ADDXrs:
1433 case AArch64::ADDSWrs:
1434 case AArch64::ADDSXrs: {
1435 unsigned Imm = MI.getOperand(3).getImm();
1436 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1437 if (ShiftVal == 0)
1438 return true;
1439 return AArch64_AM::getShiftType(Imm) == AArch64_AM::LSL && ShiftVal <= 5;
1440 }
1441
1442 case AArch64::ADDWrx:
1443 case AArch64::ADDXrx:
1444 case AArch64::ADDXrx64:
1445 case AArch64::ADDSWrx:
1446 case AArch64::ADDSXrx:
1447 case AArch64::ADDSXrx64: {
1448 unsigned Imm = MI.getOperand(3).getImm();
1450 default:
1451 return false;
1452 case AArch64_AM::UXTB:
1453 case AArch64_AM::UXTH:
1454 case AArch64_AM::UXTW:
1455 case AArch64_AM::UXTX:
1457 }
1458 }
1459
1460 case AArch64::SUBWrs:
1461 case AArch64::SUBSWrs: {
1462 unsigned Imm = MI.getOperand(3).getImm();
1463 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1464 return ShiftVal == 0 ||
1465 (AArch64_AM::getShiftType(Imm) == AArch64_AM::ASR && ShiftVal == 31);
1466 }
1467
1468 case AArch64::SUBXrs:
1469 case AArch64::SUBSXrs: {
1470 unsigned Imm = MI.getOperand(3).getImm();
1471 unsigned ShiftVal = AArch64_AM::getShiftValue(Imm);
1472 return ShiftVal == 0 ||
1473 (AArch64_AM::getShiftType(Imm) == AArch64_AM::ASR && ShiftVal == 63);
1474 }
1475
1476 case AArch64::SUBWrx:
1477 case AArch64::SUBXrx:
1478 case AArch64::SUBXrx64:
1479 case AArch64::SUBSWrx:
1480 case AArch64::SUBSXrx:
1481 case AArch64::SUBSXrx64: {
1482 unsigned Imm = MI.getOperand(3).getImm();
1484 default:
1485 return false;
1486 case AArch64_AM::UXTB:
1487 case AArch64_AM::UXTH:
1488 case AArch64_AM::UXTW:
1489 case AArch64_AM::UXTX:
1491 }
1492 }
1493
1494 case AArch64::LDRBBroW:
1495 case AArch64::LDRBBroX:
1496 case AArch64::LDRBroW:
1497 case AArch64::LDRBroX:
1498 case AArch64::LDRDroW:
1499 case AArch64::LDRDroX:
1500 case AArch64::LDRHHroW:
1501 case AArch64::LDRHHroX:
1502 case AArch64::LDRHroW:
1503 case AArch64::LDRHroX:
1504 case AArch64::LDRQroW:
1505 case AArch64::LDRQroX:
1506 case AArch64::LDRSBWroW:
1507 case AArch64::LDRSBWroX:
1508 case AArch64::LDRSBXroW:
1509 case AArch64::LDRSBXroX:
1510 case AArch64::LDRSHWroW:
1511 case AArch64::LDRSHWroX:
1512 case AArch64::LDRSHXroW:
1513 case AArch64::LDRSHXroX:
1514 case AArch64::LDRSWroW:
1515 case AArch64::LDRSWroX:
1516 case AArch64::LDRSroW:
1517 case AArch64::LDRSroX:
1518 case AArch64::LDRWroW:
1519 case AArch64::LDRWroX:
1520 case AArch64::LDRXroW:
1521 case AArch64::LDRXroX:
1522 case AArch64::PRFMroW:
1523 case AArch64::PRFMroX:
1524 case AArch64::STRBBroW:
1525 case AArch64::STRBBroX:
1526 case AArch64::STRBroW:
1527 case AArch64::STRBroX:
1528 case AArch64::STRDroW:
1529 case AArch64::STRDroX:
1530 case AArch64::STRHHroW:
1531 case AArch64::STRHHroX:
1532 case AArch64::STRHroW:
1533 case AArch64::STRHroX:
1534 case AArch64::STRQroW:
1535 case AArch64::STRQroX:
1536 case AArch64::STRSroW:
1537 case AArch64::STRSroX:
1538 case AArch64::STRWroW:
1539 case AArch64::STRWroX:
1540 case AArch64::STRXroW:
1541 case AArch64::STRXroX: {
1542 unsigned IsSigned = MI.getOperand(3).getImm();
1543 return !IsSigned;
1544 }
1545 }
1546}
1547
1548bool AArch64InstrInfo::isSEHInstruction(const MachineInstr &MI) {
1549 unsigned Opc = MI.getOpcode();
1550 switch (Opc) {
1551 default:
1552 return false;
1553 case AArch64::SEH_EndC:
1554 case AArch64::SEH_StackAlloc:
1555 case AArch64::SEH_SaveFPLR:
1556 case AArch64::SEH_SaveFPLR_X:
1557 case AArch64::SEH_SaveReg:
1558 case AArch64::SEH_SaveReg_X:
1559 case AArch64::SEH_SaveRegP:
1560 case AArch64::SEH_SaveRegP_X:
1561 case AArch64::SEH_SaveFReg:
1562 case AArch64::SEH_SaveFReg_X:
1563 case AArch64::SEH_SaveFRegP:
1564 case AArch64::SEH_SaveFRegP_X:
1565 case AArch64::SEH_SetFP:
1566 case AArch64::SEH_AddFP:
1567 case AArch64::SEH_Nop:
1568 case AArch64::SEH_PrologEnd:
1569 case AArch64::SEH_EpilogStart:
1570 case AArch64::SEH_EpilogEnd:
1571 case AArch64::SEH_PACSignLR:
1572 case AArch64::SEH_SaveAnyRegI:
1573 case AArch64::SEH_SaveAnyRegIP:
1574 case AArch64::SEH_SaveAnyRegQP:
1575 case AArch64::SEH_SaveAnyRegQPX:
1576 case AArch64::SEH_AllocZ:
1577 case AArch64::SEH_SaveZReg:
1578 case AArch64::SEH_SavePReg:
1579 return true;
1580 }
1581}
1582
1584 Register &SrcReg, Register &DstReg,
1585 unsigned &SubIdx) const {
1586 switch (MI.getOpcode()) {
1587 default:
1588 return false;
1589 case AArch64::SBFMXri: // aka sxtw
1590 case AArch64::UBFMXri: // aka uxtw
1591 // Check for the 32 -> 64 bit extension case, these instructions can do
1592 // much more.
1593 if (MI.getOperand(2).getImm() != 0 || MI.getOperand(3).getImm() != 31)
1594 return false;
1595 // This is a signed or unsigned 32 -> 64 bit extension.
1596 SrcReg = MI.getOperand(1).getReg();
1597 DstReg = MI.getOperand(0).getReg();
1598 SubIdx = AArch64::sub_32;
1599 return true;
1600 }
1601}
1602
1604 const MachineInstr &MIa, const MachineInstr &MIb) const {
1605 const MachineOperand *BaseOpA = nullptr, *BaseOpB = nullptr;
1606 int64_t OffsetA = 0, OffsetB = 0;
1607 TypeSize WidthA(0, false), WidthB(0, false);
1608 bool OffsetAIsScalable = false, OffsetBIsScalable = false;
1609
1610 assert(MIa.mayLoadOrStore() && "MIa must be a load or store.");
1611 assert(MIb.mayLoadOrStore() && "MIb must be a load or store.");
1612
1615 return false;
1616
1617 // Retrieve the base, offset from the base and width. Width
1618 // is the size of memory that is being loaded/stored (e.g. 1, 2, 4, 8). If
1619 // base are identical, and the offset of a lower memory access +
1620 // the width doesn't overlap the offset of a higher memory access,
1621 // then the memory accesses are different.
1622 // If OffsetAIsScalable and OffsetBIsScalable are both true, they
1623 // are assumed to have the same scale (vscale).
1624 if (getMemOperandWithOffsetWidth(MIa, BaseOpA, OffsetA, OffsetAIsScalable,
1625 WidthA) &&
1626 getMemOperandWithOffsetWidth(MIb, BaseOpB, OffsetB, OffsetBIsScalable,
1627 WidthB)) {
1628 if (BaseOpA->isIdenticalTo(*BaseOpB) &&
1629 OffsetAIsScalable == OffsetBIsScalable) {
1630 int LowOffset = OffsetA < OffsetB ? OffsetA : OffsetB;
1631 int HighOffset = OffsetA < OffsetB ? OffsetB : OffsetA;
1632 TypeSize LowWidth = (LowOffset == OffsetA) ? WidthA : WidthB;
1633 if (LowWidth.isScalable() == OffsetAIsScalable &&
1634 LowOffset + (int)LowWidth.getKnownMinValue() <= HighOffset)
1635 return true;
1636 }
1637 }
1638 return false;
1639}
1640
1642 const MachineBasicBlock *MBB,
1643 const MachineFunction &MF) const {
1645 return true;
1646
1647 // Do not move an instruction that can be recognized as a branch target.
1648 if (hasBTISemantics(MI))
1649 return true;
1650
1651 switch (MI.getOpcode()) {
1652 case AArch64::HINT:
1653 // CSDB hints are scheduling barriers.
1654 if (MI.getOperand(0).getImm() == 0x14)
1655 return true;
1656 break;
1657 case AArch64::DSB:
1658 case AArch64::ISB:
1659 // DSB and ISB also are scheduling barriers.
1660 return true;
1661 case AArch64::MSRpstatesvcrImm1:
1662 // SMSTART and SMSTOP are also scheduling barriers.
1663 return true;
1664 default:;
1665 }
1666 if (isSEHInstruction(MI))
1667 return true;
1668 // Skip debug instructions and pseudo probes so they do not change
1669 // scheduling regions.
1670 auto Next = next_nodbg(MI.getIterator(), MBB->instr_end());
1671 return Next != MBB->instr_end() && Next->isCFIInstruction();
1672}
1673
1674/// analyzeCompare - For a comparison instruction, return the source registers
1675/// in SrcReg and SrcReg2, and the value it compares against in CmpValue.
1676/// Return true if the comparison instruction can be analyzed.
1678 Register &SrcReg2, int64_t &CmpMask,
1679 int64_t &CmpValue) const {
1680 // The first operand can be a frame index where we'd normally expect a
1681 // register.
1682 // FIXME: Pass subregisters out of analyzeCompare
1683 assert(MI.getNumOperands() >= 2 && "All AArch64 cmps should have 2 operands");
1684 if (!MI.getOperand(1).isReg() || MI.getOperand(1).getSubReg())
1685 return false;
1686
1687 switch (MI.getOpcode()) {
1688 default:
1689 break;
1690 case AArch64::PTEST_PP:
1691 case AArch64::PTEST_PP_ANY:
1692 case AArch64::PTEST_PP_FIRST:
1693 SrcReg = MI.getOperand(0).getReg();
1694 SrcReg2 = MI.getOperand(1).getReg();
1695 if (MI.getOperand(2).getSubReg())
1696 return false;
1697
1698 // Not sure about the mask and value for now...
1699 CmpMask = ~0;
1700 CmpValue = 0;
1701 return true;
1702 case AArch64::SUBSWrr:
1703 case AArch64::SUBSWrs:
1704 case AArch64::SUBSWrx:
1705 case AArch64::SUBSXrr:
1706 case AArch64::SUBSXrs:
1707 case AArch64::SUBSXrx:
1708 case AArch64::ADDSWrr:
1709 case AArch64::ADDSWrs:
1710 case AArch64::ADDSWrx:
1711 case AArch64::ADDSXrr:
1712 case AArch64::ADDSXrs:
1713 case AArch64::ADDSXrx:
1714 // Replace SUBSWrr with SUBWrr if NZCV is not used.
1715 SrcReg = MI.getOperand(1).getReg();
1716 SrcReg2 = MI.getOperand(2).getReg();
1717
1718 // FIXME: Pass subregisters out of analyzeCompare
1719 if (MI.getOperand(2).getSubReg())
1720 return false;
1721
1722 CmpMask = ~0;
1723 CmpValue = 0;
1724 return true;
1725 case AArch64::SUBSWri:
1726 case AArch64::ADDSWri:
1727 case AArch64::SUBSXri:
1728 case AArch64::ADDSXri:
1729 SrcReg = MI.getOperand(1).getReg();
1730 SrcReg2 = 0;
1731 CmpMask = ~0;
1732 CmpValue = MI.getOperand(2).getImm();
1733 return true;
1734 case AArch64::ANDSWri:
1735 case AArch64::ANDSXri:
1736 // ANDS does not use the same encoding scheme as the others xxxS
1737 // instructions.
1738 SrcReg = MI.getOperand(1).getReg();
1739 SrcReg2 = 0;
1740 CmpMask = ~0;
1742 MI.getOperand(2).getImm(),
1743 MI.getOpcode() == AArch64::ANDSWri ? 32 : 64);
1744 return true;
1745 }
1746
1747 return false;
1748}
1749
1751 MachineBasicBlock *MBB = Instr.getParent();
1752 assert(MBB && "Can't get MachineBasicBlock here");
1753 MachineFunction *MF = MBB->getParent();
1754 assert(MF && "Can't get MachineFunction here");
1758
1759 for (unsigned OpIdx = 0, EndIdx = Instr.getNumOperands(); OpIdx < EndIdx;
1760 ++OpIdx) {
1761 MachineOperand &MO = Instr.getOperand(OpIdx);
1762 const TargetRegisterClass *OpRegCstraints =
1763 Instr.getRegClassConstraint(OpIdx, TII, TRI);
1764
1765 // If there's no constraint, there's nothing to do.
1766 if (!OpRegCstraints)
1767 continue;
1768 // If the operand is a frame index, there's nothing to do here.
1769 // A frame index operand will resolve correctly during PEI.
1770 if (MO.isFI())
1771 continue;
1772
1773 assert(MO.isReg() &&
1774 "Operand has register constraints without being a register!");
1775
1776 Register Reg = MO.getReg();
1777 if (Reg.isPhysical()) {
1778 if (!OpRegCstraints->contains(Reg))
1779 return false;
1780 } else if (!OpRegCstraints->hasSubClassEq(MRI->getRegClass(Reg)) &&
1781 !MRI->constrainRegClass(Reg, OpRegCstraints))
1782 return false;
1783 }
1784
1785 return true;
1786}
1787
1788/// Return the opcode that does not set flags when possible - otherwise
1789/// return the original opcode. The caller is responsible to do the actual
1790/// substitution and legality checking.
1792 // Don't convert all compare instructions, because for some the zero register
1793 // encoding becomes the sp register.
1794 bool MIDefinesZeroReg = false;
1795 if (MI.definesRegister(AArch64::WZR, /*TRI=*/nullptr) ||
1796 MI.definesRegister(AArch64::XZR, /*TRI=*/nullptr))
1797 MIDefinesZeroReg = true;
1798
1799 switch (MI.getOpcode()) {
1800 default:
1801 return MI.getOpcode();
1802 case AArch64::ADDSWrr:
1803 return AArch64::ADDWrr;
1804 case AArch64::ADDSWri:
1805 return MIDefinesZeroReg ? AArch64::ADDSWri : AArch64::ADDWri;
1806 case AArch64::ADDSWrs:
1807 return MIDefinesZeroReg ? AArch64::ADDSWrs : AArch64::ADDWrs;
1808 case AArch64::ADDSWrx:
1809 return AArch64::ADDWrx;
1810 case AArch64::ADDSXrr:
1811 return AArch64::ADDXrr;
1812 case AArch64::ADDSXri:
1813 return MIDefinesZeroReg ? AArch64::ADDSXri : AArch64::ADDXri;
1814 case AArch64::ADDSXrs:
1815 return MIDefinesZeroReg ? AArch64::ADDSXrs : AArch64::ADDXrs;
1816 case AArch64::ADDSXrx:
1817 return AArch64::ADDXrx;
1818 case AArch64::SUBSWrr:
1819 return AArch64::SUBWrr;
1820 case AArch64::SUBSWri:
1821 return MIDefinesZeroReg ? AArch64::SUBSWri : AArch64::SUBWri;
1822 case AArch64::SUBSWrs:
1823 return MIDefinesZeroReg ? AArch64::SUBSWrs : AArch64::SUBWrs;
1824 case AArch64::SUBSWrx:
1825 return AArch64::SUBWrx;
1826 case AArch64::SUBSXrr:
1827 return AArch64::SUBXrr;
1828 case AArch64::SUBSXri:
1829 return MIDefinesZeroReg ? AArch64::SUBSXri : AArch64::SUBXri;
1830 case AArch64::SUBSXrs:
1831 return MIDefinesZeroReg ? AArch64::SUBSXrs : AArch64::SUBXrs;
1832 case AArch64::SUBSXrx:
1833 return AArch64::SUBXrx;
1834 }
1835}
1836
1837enum AccessKind { AK_Write = 0x01, AK_Read = 0x10, AK_All = 0x11 };
1838
1839/// True when condition flags are accessed (either by writing or reading)
1840/// on the instruction trace starting at From and ending at To.
1841///
1842/// Note: If From and To are from different blocks it's assumed CC are accessed
1843/// on the path.
1846 const TargetRegisterInfo *TRI, const AccessKind AccessToCheck = AK_All) {
1847 // Early exit if To is at the beginning of the BB.
1848 if (To == To->getParent()->begin())
1849 return true;
1850
1851 // Check whether the instructions are in the same basic block
1852 // If not, assume the condition flags might get modified somewhere.
1853 if (To->getParent() != From->getParent())
1854 return true;
1855
1856 // From must be above To.
1857 assert(std::any_of(
1858 ++To.getReverse(), To->getParent()->rend(),
1859 [From](MachineInstr &MI) { return MI.getIterator() == From; }));
1860
1861 // We iterate backward starting at \p To until we hit \p From.
1862 for (const MachineInstr &Instr :
1864 if (((AccessToCheck & AK_Write) &&
1865 Instr.modifiesRegister(AArch64::NZCV, TRI)) ||
1866 ((AccessToCheck & AK_Read) && Instr.readsRegister(AArch64::NZCV, TRI)))
1867 return true;
1868 }
1869 return false;
1870}
1871
1872std::optional<unsigned>
1873AArch64InstrInfo::canRemovePTestInstr(MachineInstr *PTest, MachineInstr *Mask,
1874 MachineInstr *Pred,
1875 const MachineRegisterInfo *MRI) const {
1876 unsigned MaskOpcode = Mask->getOpcode();
1877 unsigned PredOpcode = Pred->getOpcode();
1878 bool PredIsPTestLike = isPTestLikeOpcode(PredOpcode);
1879 bool PredIsWhileLike = isWhileOpcode(PredOpcode);
1880
1881 if (PredIsWhileLike) {
1882 // For PTEST(PG, PG), PTEST is redundant when PG is the result of a WHILEcc
1883 // instruction and the condition is "any" since WHILcc does an implicit
1884 // PTEST(ALL, PG) check and PG is always a subset of ALL.
1885 if ((Mask == Pred) && PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1886 return PredOpcode;
1887
1888 // For PTEST(PTRUE_ALL, WHILE), if the element size matches, the PTEST is
1889 // redundant since WHILE performs an implicit PTEST with an all active
1890 // mask.
1891 if (isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31 &&
1892 getElementSizeForOpcode(MaskOpcode) ==
1893 getElementSizeForOpcode(PredOpcode))
1894 return PredOpcode;
1895
1896 // For PTEST_FIRST(PTRUE_ALL, WHILE), the PTEST_FIRST is redundant since
1897 // WHILEcc performs an implicit PTEST with an all active mask, setting
1898 // the N flag as the PTEST_FIRST would.
1899 if (PTest->getOpcode() == AArch64::PTEST_PP_FIRST &&
1900 isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31)
1901 return PredOpcode;
1902
1903 return {};
1904 }
1905
1906 if (PredIsPTestLike) {
1907 // For PTEST(PG, PG), PTEST is redundant when PG is the result of an
1908 // instruction that sets the flags as PTEST would and the condition is
1909 // "any" since PG is always a subset of the governing predicate of the
1910 // ptest-like instruction.
1911 if ((Mask == Pred) && PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1912 return PredOpcode;
1913
1914 auto PTestLikeMask = MRI->getUniqueVRegDef(Pred->getOperand(1).getReg());
1915
1916 // If the PTEST like instruction's general predicate is not `Mask`, attempt
1917 // to look through a copy and try again. This is because some instructions
1918 // take a predicate whose register class is a subset of its result class.
1919 if (Mask != PTestLikeMask && PTestLikeMask->isFullCopy() &&
1920 PTestLikeMask->getOperand(1).getReg().isVirtual())
1921 PTestLikeMask =
1922 MRI->getUniqueVRegDef(PTestLikeMask->getOperand(1).getReg());
1923
1924 // For PTEST(PTRUE_ALL, PTEST_LIKE), the PTEST is redundant if the
1925 // the element size matches and either the PTEST_LIKE instruction uses
1926 // the same all active mask or the condition is "any".
1927 if (isPTrueOpcode(MaskOpcode) && Mask->getOperand(1).getImm() == 31 &&
1928 getElementSizeForOpcode(MaskOpcode) ==
1929 getElementSizeForOpcode(PredOpcode)) {
1930 if (Mask == PTestLikeMask || PTest->getOpcode() == AArch64::PTEST_PP_ANY)
1931 return PredOpcode;
1932 }
1933
1934 // For PTEST(PG, PTEST_LIKE(PG, ...)), the PTEST is redundant since the
1935 // flags are set based on the same mask 'PG', but PTEST_LIKE must operate
1936 // on 8-bit predicates like the PTEST. Otherwise, for instructions like
1937 // compare that also support 16/32/64-bit predicates, the implicit PTEST
1938 // performed by the compare could consider fewer lanes for these element
1939 // sizes.
1940 //
1941 // For example, consider
1942 //
1943 // ptrue p0.b ; P0=1111-1111-1111-1111
1944 // index z0.s, #0, #1 ; Z0=<0,1,2,3>
1945 // index z1.s, #1, #1 ; Z1=<1,2,3,4>
1946 // cmphi p1.s, p0/z, z1.s, z0.s ; P1=0001-0001-0001-0001
1947 // ; ^ last active
1948 // ptest p0, p1.b ; P1=0001-0001-0001-0001
1949 // ; ^ last active
1950 //
1951 // where the compare generates a canonical all active 32-bit predicate
1952 // (equivalent to 'ptrue p1.s, all'). The implicit PTEST sets the last
1953 // active flag, whereas the PTEST instruction with the same mask doesn't.
1954 // For PTEST_ANY this doesn't apply as the flags in this case would be
1955 // identical regardless of element size.
1956 uint64_t PredElementSize = getElementSizeForOpcode(PredOpcode);
1957 if (Mask == PTestLikeMask && (PredElementSize == AArch64::ElementSizeB ||
1958 PTest->getOpcode() == AArch64::PTEST_PP_ANY))
1959 return PredOpcode;
1960
1961 return {};
1962 }
1963
1964 // If OP in PTEST(PG, OP(PG, ...)) has a flag-setting variant change the
1965 // opcode so the PTEST becomes redundant.
1966 switch (PredOpcode) {
1967 case AArch64::AND_PPzPP:
1968 case AArch64::BIC_PPzPP:
1969 case AArch64::EOR_PPzPP:
1970 case AArch64::NAND_PPzPP:
1971 case AArch64::NOR_PPzPP:
1972 case AArch64::ORN_PPzPP:
1973 case AArch64::ORR_PPzPP:
1974 case AArch64::BRKA_PPzP:
1975 case AArch64::BRKPA_PPzPP:
1976 case AArch64::BRKB_PPzP:
1977 case AArch64::BRKPB_PPzPP:
1978 case AArch64::RDFFR_PPz: {
1979 // Check to see if our mask is the same. If not the resulting flag bits
1980 // may be different and we can't remove the ptest.
1981 auto *PredMask = MRI->getUniqueVRegDef(Pred->getOperand(1).getReg());
1982 if (Mask != PredMask)
1983 return {};
1984 break;
1985 }
1986 case AArch64::BRKN_PPzP: {
1987 // BRKN uses an all active implicit mask to set flags unlike the other
1988 // flag-setting instructions.
1989 // PTEST(PTRUE_B(31), BRKN(PG, A, B)) -> BRKNS(PG, A, B).
1990 if ((MaskOpcode != AArch64::PTRUE_B) ||
1991 (Mask->getOperand(1).getImm() != 31))
1992 return {};
1993 break;
1994 }
1995 case AArch64::PTRUE_B:
1996 // PTEST(OP=PTRUE_B(A), OP) -> PTRUES_B(A)
1997 break;
1998 default:
1999 // Bail out if we don't recognize the input
2000 return {};
2001 }
2002
2003 return convertToFlagSettingOpc(PredOpcode);
2004}
2005
2006/// optimizePTestInstr - Attempt to remove a ptest of a predicate-generating
2007/// operation which could set the flags in an identical manner
2008bool AArch64InstrInfo::optimizePTestInstr(
2009 MachineInstr *PTest, unsigned MaskReg, unsigned PredReg,
2010 const MachineRegisterInfo *MRI) const {
2011 auto *Mask = MRI->getUniqueVRegDef(MaskReg);
2012 auto *Pred = MRI->getUniqueVRegDef(PredReg);
2013
2014 if (Pred->isCopy() && PTest->getOpcode() == AArch64::PTEST_PP_FIRST) {
2015 // Instructions which return a multi-vector (e.g. WHILECC_x2) require copies
2016 // before the branch to extract each subregister.
2017 auto Op = Pred->getOperand(1);
2018 if (Op.isReg() && Op.getReg().isVirtual() &&
2019 Op.getSubReg() == AArch64::psub0)
2020 Pred = MRI->getUniqueVRegDef(Op.getReg());
2021 }
2022
2023 unsigned PredOpcode = Pred->getOpcode();
2024 auto NewOp = canRemovePTestInstr(PTest, Mask, Pred, MRI);
2025 if (!NewOp)
2026 return false;
2027
2028 const TargetRegisterInfo *TRI = &getRegisterInfo();
2029
2030 // If another instruction between Pred and PTest accesses flags, don't remove
2031 // the ptest or update the earlier instruction to modify them.
2032 if (areCFlagsAccessedBetweenInstrs(Pred, PTest, TRI))
2033 return false;
2034
2035 // If we pass all the checks, it's safe to remove the PTEST and use the flags
2036 // as they are prior to PTEST. Sometimes this requires the tested PTEST
2037 // operand to be replaced with an equivalent instruction that also sets the
2038 // flags.
2039 PTest->eraseFromParent();
2040 if (*NewOp != PredOpcode) {
2041 Pred->setDesc(get(*NewOp));
2042 bool succeeded = UpdateOperandRegClass(*Pred);
2043 (void)succeeded;
2044 assert(succeeded && "Operands have incompatible register classes!");
2045 Pred->addRegisterDefined(AArch64::NZCV, TRI);
2046 }
2047
2048 // Ensure that the flags def is live.
2049 if (Pred->registerDefIsDead(AArch64::NZCV, TRI)) {
2050 unsigned i = 0, e = Pred->getNumOperands();
2051 for (; i != e; ++i) {
2052 MachineOperand &MO = Pred->getOperand(i);
2053 if (MO.isReg() && MO.isDef() && MO.getReg() == AArch64::NZCV) {
2054 MO.setIsDead(false);
2055 break;
2056 }
2057 }
2058 }
2059 return true;
2060}
2061
2062/// Try to optimize a compare instruction. A compare instruction is an
2063/// instruction which produces AArch64::NZCV. It can be truly compare
2064/// instruction
2065/// when there are no uses of its destination register.
2066///
2067/// The following steps are tried in order:
2068/// 1. Convert CmpInstr into an unconditional version.
2069/// 2. Remove CmpInstr if above there is an instruction producing a needed
2070/// condition code or an instruction which can be converted into such an
2071/// instruction.
2072/// Only comparison with zero is supported.
2074 MachineInstr &CmpInstr, Register SrcReg, Register SrcReg2, int64_t CmpMask,
2075 int64_t CmpValue, const MachineRegisterInfo *MRI) const {
2076 assert(CmpInstr.getParent());
2077 assert(MRI);
2078
2079 // Replace SUBSWrr with SUBWrr if NZCV is not used.
2080 int DeadNZCVIdx =
2081 CmpInstr.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true);
2082 if (DeadNZCVIdx != -1) {
2083 if (CmpInstr.definesRegister(AArch64::WZR, /*TRI=*/nullptr) ||
2084 CmpInstr.definesRegister(AArch64::XZR, /*TRI=*/nullptr)) {
2085 CmpInstr.eraseFromParent();
2086 return true;
2087 }
2088 unsigned Opc = CmpInstr.getOpcode();
2089 unsigned NewOpc = convertToNonFlagSettingOpc(CmpInstr);
2090 if (NewOpc == Opc)
2091 return false;
2092 const MCInstrDesc &MCID = get(NewOpc);
2093 CmpInstr.setDesc(MCID);
2094 CmpInstr.removeOperand(DeadNZCVIdx);
2095 bool succeeded = UpdateOperandRegClass(CmpInstr);
2096 (void)succeeded;
2097 assert(succeeded && "Some operands reg class are incompatible!");
2098 return true;
2099 }
2100
2101 if (CmpInstr.getOpcode() == AArch64::PTEST_PP ||
2102 CmpInstr.getOpcode() == AArch64::PTEST_PP_ANY ||
2103 CmpInstr.getOpcode() == AArch64::PTEST_PP_FIRST)
2104 return optimizePTestInstr(&CmpInstr, SrcReg, SrcReg2, MRI);
2105
2106 if (SrcReg2 != 0)
2107 return false;
2108
2109 // CmpInstr is a Compare instruction if destination register is not used.
2110 if (!MRI->use_nodbg_empty(CmpInstr.getOperand(0).getReg()))
2111 return false;
2112
2113 if (CmpValue == 0 && substituteCmpToZero(CmpInstr, SrcReg, *MRI))
2114 return true;
2115 return (CmpValue == 0 || CmpValue == 1) &&
2116 removeCmpToZeroOrOne(CmpInstr, SrcReg, CmpValue, *MRI);
2117}
2118
2119/// Get opcode of S version of Instr.
2120/// If Instr is S version its opcode is returned.
2121/// AArch64::INSTRUCTION_LIST_END is returned if Instr does not have S version
2122/// or we are not interested in it.
2123static unsigned sForm(MachineInstr &Instr) {
2124 switch (Instr.getOpcode()) {
2125 default:
2126 return AArch64::INSTRUCTION_LIST_END;
2127
2128 case AArch64::ADDSWrr:
2129 case AArch64::ADDSWri:
2130 case AArch64::ADDSXrr:
2131 case AArch64::ADDSXri:
2132 case AArch64::ADDSWrx:
2133 case AArch64::ADDSXrx:
2134 case AArch64::ADDSWrs:
2135 case AArch64::ADDSXrs:
2136 case AArch64::SUBSWrr:
2137 case AArch64::SUBSWri:
2138 case AArch64::SUBSWrx:
2139 case AArch64::SUBSWrs:
2140 case AArch64::SUBSXrr:
2141 case AArch64::SUBSXri:
2142 case AArch64::SUBSXrx:
2143 case AArch64::SUBSXrs:
2144 case AArch64::ANDSWri:
2145 case AArch64::ANDSWrr:
2146 case AArch64::ANDSWrs:
2147 case AArch64::ANDSXri:
2148 case AArch64::ANDSXrr:
2149 case AArch64::ANDSXrs:
2150 case AArch64::BICSWrr:
2151 case AArch64::BICSXrr:
2152 case AArch64::BICSWrs:
2153 case AArch64::BICSXrs:
2154 case AArch64::ADCSWr:
2155 case AArch64::ADCSXr:
2156 case AArch64::SBCSWr:
2157 case AArch64::SBCSXr:
2158 return Instr.getOpcode();
2159
2160 case AArch64::ADDWrr:
2161 return AArch64::ADDSWrr;
2162 case AArch64::ADDWri:
2163 return AArch64::ADDSWri;
2164 case AArch64::ADDXrr:
2165 return AArch64::ADDSXrr;
2166 case AArch64::ADDXri:
2167 return AArch64::ADDSXri;
2168 case AArch64::ADDWrx:
2169 return AArch64::ADDSWrx;
2170 case AArch64::ADDXrx:
2171 return AArch64::ADDSXrx;
2172 case AArch64::ADDWrs:
2173 return AArch64::ADDSWrs;
2174 case AArch64::ADDXrs:
2175 return AArch64::ADDSXrs;
2176 case AArch64::ADCWr:
2177 return AArch64::ADCSWr;
2178 case AArch64::ADCXr:
2179 return AArch64::ADCSXr;
2180 case AArch64::SUBWrr:
2181 return AArch64::SUBSWrr;
2182 case AArch64::SUBWri:
2183 return AArch64::SUBSWri;
2184 case AArch64::SUBXrr:
2185 return AArch64::SUBSXrr;
2186 case AArch64::SUBXri:
2187 return AArch64::SUBSXri;
2188 case AArch64::SUBWrx:
2189 return AArch64::SUBSWrx;
2190 case AArch64::SUBXrx:
2191 return AArch64::SUBSXrx;
2192 case AArch64::SUBWrs:
2193 return AArch64::SUBSWrs;
2194 case AArch64::SUBXrs:
2195 return AArch64::SUBSXrs;
2196 case AArch64::SBCWr:
2197 return AArch64::SBCSWr;
2198 case AArch64::SBCXr:
2199 return AArch64::SBCSXr;
2200 case AArch64::ANDWri:
2201 return AArch64::ANDSWri;
2202 case AArch64::ANDXri:
2203 return AArch64::ANDSXri;
2204 case AArch64::ANDWrr:
2205 return AArch64::ANDSWrr;
2206 case AArch64::ANDWrs:
2207 return AArch64::ANDSWrs;
2208 case AArch64::ANDXrr:
2209 return AArch64::ANDSXrr;
2210 case AArch64::ANDXrs:
2211 return AArch64::ANDSXrs;
2212 case AArch64::BICWrr:
2213 return AArch64::BICSWrr;
2214 case AArch64::BICXrr:
2215 return AArch64::BICSXrr;
2216 case AArch64::BICWrs:
2217 return AArch64::BICSWrs;
2218 case AArch64::BICXrs:
2219 return AArch64::BICSXrs;
2220 }
2221}
2222
2223/// Check if AArch64::NZCV should be alive in successors of MBB.
2225 for (auto *BB : MBB->successors())
2226 if (BB->isLiveIn(AArch64::NZCV))
2227 return true;
2228 return false;
2229}
2230
2231/// \returns The condition code operand index for \p Instr if it is a branch
2232/// or select and -1 otherwise.
2233int AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(
2234 const MachineInstr &Instr) {
2235 switch (Instr.getOpcode()) {
2236 default:
2237 return -1;
2238
2239 case AArch64::Bcc: {
2240 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV, /*TRI=*/nullptr);
2241 assert(Idx >= 2);
2242 return Idx - 2;
2243 }
2244
2245 case AArch64::CSINVWr:
2246 case AArch64::CSINVXr:
2247 case AArch64::CSINCWr:
2248 case AArch64::CSINCXr:
2249 case AArch64::CSELWr:
2250 case AArch64::CSELXr:
2251 case AArch64::CSNEGWr:
2252 case AArch64::CSNEGXr:
2253 case AArch64::FCSELSrrr:
2254 case AArch64::FCSELDrrr: {
2255 int Idx = Instr.findRegisterUseOperandIdx(AArch64::NZCV, /*TRI=*/nullptr);
2256 assert(Idx >= 1);
2257 return Idx - 1;
2258 }
2259 }
2260}
2261
2262/// Find a condition code used by the instruction.
2263/// Returns AArch64CC::Invalid if either the instruction does not use condition
2264/// codes or we don't optimize CmpInstr in the presence of such instructions.
2266 int CCIdx =
2267 AArch64InstrInfo::findCondCodeUseOperandIdxForBranchOrSelect(Instr);
2268 return CCIdx >= 0 ? static_cast<AArch64CC::CondCode>(
2269 Instr.getOperand(CCIdx).getImm())
2271}
2272
2275 UsedNZCV UsedFlags;
2276 switch (CC) {
2277 default:
2278 break;
2279
2280 case AArch64CC::EQ: // Z set
2281 case AArch64CC::NE: // Z clear
2282 UsedFlags.Z = true;
2283 break;
2284
2285 case AArch64CC::HI: // Z clear and C set
2286 case AArch64CC::LS: // Z set or C clear
2287 UsedFlags.Z = true;
2288 [[fallthrough]];
2289 case AArch64CC::HS: // C set
2290 case AArch64CC::LO: // C clear
2291 UsedFlags.C = true;
2292 break;
2293
2294 case AArch64CC::MI: // N set
2295 case AArch64CC::PL: // N clear
2296 UsedFlags.N = true;
2297 break;
2298
2299 case AArch64CC::VS: // V set
2300 case AArch64CC::VC: // V clear
2301 UsedFlags.V = true;
2302 break;
2303
2304 case AArch64CC::GT: // Z clear, N and V the same
2305 case AArch64CC::LE: // Z set, N and V differ
2306 UsedFlags.Z = true;
2307 [[fallthrough]];
2308 case AArch64CC::GE: // N and V the same
2309 case AArch64CC::LT: // N and V differ
2310 UsedFlags.N = true;
2311 UsedFlags.V = true;
2312 break;
2313 }
2314 return UsedFlags;
2315}
2316
2317/// \returns Conditions flags used after \p CmpInstr in its MachineBB if NZCV
2318/// flags are not alive in successors of the same \p CmpInstr and \p MI parent.
2319/// \returns std::nullopt otherwise.
2320///
2321/// Collect instructions using that flags in \p CCUseInstrs if provided.
2322std::optional<UsedNZCV>
2324 const TargetRegisterInfo &TRI,
2325 SmallVectorImpl<MachineInstr *> *CCUseInstrs) {
2326 MachineBasicBlock *CmpParent = CmpInstr.getParent();
2327 if (MI.getParent() != CmpParent)
2328 return std::nullopt;
2329
2330 if (areCFlagsAliveInSuccessors(CmpParent))
2331 return std::nullopt;
2332
2333 UsedNZCV NZCVUsedAfterCmp;
2335 std::next(CmpInstr.getIterator()), CmpParent->instr_end())) {
2336 if (Instr.readsRegister(AArch64::NZCV, &TRI)) {
2338 if (CC == AArch64CC::Invalid) // Unsupported conditional instruction
2339 return std::nullopt;
2340 NZCVUsedAfterCmp |= getUsedNZCV(CC);
2341 if (CCUseInstrs)
2342 CCUseInstrs->push_back(&Instr);
2343 }
2344 if (Instr.modifiesRegister(AArch64::NZCV, &TRI))
2345 break;
2346 }
2347 return NZCVUsedAfterCmp;
2348}
2349
2350static bool isADDSRegImm(unsigned Opcode) {
2351 return Opcode == AArch64::ADDSWri || Opcode == AArch64::ADDSXri;
2352}
2353
2354static bool isSUBSRegImm(unsigned Opcode) {
2355 return Opcode == AArch64::SUBSWri || Opcode == AArch64::SUBSXri;
2356}
2357
2359 unsigned Opc = sForm(MI);
2360 switch (Opc) {
2361 case AArch64::ANDSWri:
2362 case AArch64::ANDSWrr:
2363 case AArch64::ANDSWrs:
2364 case AArch64::ANDSXri:
2365 case AArch64::ANDSXrr:
2366 case AArch64::ANDSXrs:
2367 case AArch64::BICSWrr:
2368 case AArch64::BICSXrr:
2369 case AArch64::BICSWrs:
2370 case AArch64::BICSXrs:
2371 return true;
2372 default:
2373 return false;
2374 }
2375}
2376
2377/// Check if CmpInstr can be substituted by MI.
2378///
2379/// CmpInstr can be substituted:
2380/// - CmpInstr is either 'ADDS %vreg, 0' or 'SUBS %vreg, 0'
2381/// - and, MI and CmpInstr are from the same MachineBB
2382/// - and, condition flags are not alive in successors of the CmpInstr parent
2383/// - and, if MI opcode is the S form there must be no defs of flags between
2384/// MI and CmpInstr
2385/// or if MI opcode is not the S form there must be neither defs of flags
2386/// nor uses of flags between MI and CmpInstr.
2387/// - and, C is not used after CmpInstr; CmpInstr's C is from adds/subs #0 on
2388/// SrcReg and can differ from MI (e.g. carry out of ADCS/SBCS).
2389/// - and, V is not used after CmpInstr unless MI is AND/BIC (V cleared) or MI
2390/// has NoSWrap (overflow is poison and the fold is still safe).
2392 const TargetRegisterInfo &TRI) {
2393 // MI is an opcode sForm maps (add/sub/adc/sbc/and/bic and their S forms).
2394 assert(sForm(MI) != AArch64::INSTRUCTION_LIST_END);
2395
2396 const unsigned CmpOpcode = CmpInstr.getOpcode();
2397 if (!isADDSRegImm(CmpOpcode) && !isSUBSRegImm(CmpOpcode))
2398 return false;
2399
2400 assert((CmpInstr.getOperand(2).isImm() &&
2401 CmpInstr.getOperand(2).getImm() == 0) &&
2402 "Caller guarantees that CmpInstr compares with constant 0");
2403
2404 std::optional<UsedNZCV> NZVCUsed = examineCFlagsUse(MI, CmpInstr, TRI);
2405 if (!NZVCUsed || NZVCUsed->C)
2406 return false;
2407
2408 // CmpInstr is ADDS/SUBS with immediate 0 on SrcReg (compare SrcReg to zero).
2409 // After the fold, users see NZCV from MI (or its S form), not from CmpInstr.
2410 // N/Z match CmpInstr for the value in SrcReg; C/V need not match in general
2411 // (e.g. ADCS vs adds #0), so we require C unused after CmpInstr and gate V
2412 // as below. NoSWrap makes signed overflow poison; AND/BIC clear V.
2413 if (NZVCUsed->V && !MI.getFlag(MachineInstr::NoSWrap) && !isANDOpcode(MI))
2414 return false;
2415
2416 AccessKind AccessToCheck = AK_Write;
2417 if (sForm(MI) != MI.getOpcode())
2418 AccessToCheck = AK_All;
2419 return !areCFlagsAccessedBetweenInstrs(&MI, &CmpInstr, &TRI, AccessToCheck);
2420}
2421
2422/// Substitute an instruction comparing to zero with another instruction
2423/// which produces needed condition flags.
2424///
2425/// Return true on success.
2426bool AArch64InstrInfo::substituteCmpToZero(
2427 MachineInstr &CmpInstr, unsigned SrcReg,
2428 const MachineRegisterInfo &MRI) const {
2429 // Get the unique definition of SrcReg.
2430 MachineInstr *MI = MRI.getUniqueVRegDef(SrcReg);
2431 if (!MI)
2432 return false;
2433
2434 const TargetRegisterInfo &TRI = getRegisterInfo();
2435
2436 unsigned NewOpc = sForm(*MI);
2437 if (NewOpc == AArch64::INSTRUCTION_LIST_END)
2438 return false;
2439
2440 if (!canInstrSubstituteCmpInstr(*MI, CmpInstr, TRI))
2441 return false;
2442
2443 // Update the instruction to set NZCV.
2444 MI->setDesc(get(NewOpc));
2445 CmpInstr.eraseFromParent();
2447 (void)succeeded;
2448 assert(succeeded && "Some operands reg class are incompatible!");
2449 MI->addRegisterDefined(AArch64::NZCV, &TRI);
2450 return true;
2451}
2452
2453/// \returns True if \p CmpInstr can be removed.
2454///
2455/// \p IsInvertCC is true if, after removing \p CmpInstr, condition
2456/// codes used in \p CCUseInstrs must be inverted.
2458 int CmpValue, const TargetRegisterInfo &TRI,
2460 bool &IsInvertCC) {
2461 assert((CmpValue == 0 || CmpValue == 1) &&
2462 "Only comparisons to 0 or 1 considered for removal!");
2463
2464 // MI is 'CSINCWr %vreg, wzr, wzr, <cc>' or 'CSINCXr %vreg, xzr, xzr, <cc>'
2465 unsigned MIOpc = MI.getOpcode();
2466 if (MIOpc == AArch64::CSINCWr) {
2467 if (MI.getOperand(1).getReg() != AArch64::WZR ||
2468 MI.getOperand(2).getReg() != AArch64::WZR)
2469 return false;
2470 } else if (MIOpc == AArch64::CSINCXr) {
2471 if (MI.getOperand(1).getReg() != AArch64::XZR ||
2472 MI.getOperand(2).getReg() != AArch64::XZR)
2473 return false;
2474 } else {
2475 return false;
2476 }
2478 if (MICC == AArch64CC::Invalid)
2479 return false;
2480
2481 // NZCV needs to be defined
2482 if (MI.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) != -1)
2483 return false;
2484
2485 // CmpInstr is 'ADDS %vreg, 0' or 'SUBS %vreg, 0' or 'SUBS %vreg, 1'
2486 const unsigned CmpOpcode = CmpInstr.getOpcode();
2487 bool IsSubsRegImm = isSUBSRegImm(CmpOpcode);
2488 if (CmpValue && !IsSubsRegImm)
2489 return false;
2490 if (!CmpValue && !IsSubsRegImm && !isADDSRegImm(CmpOpcode))
2491 return false;
2492
2493 // MI conditions allowed: eq, ne, mi, pl
2494 UsedNZCV MIUsedNZCV = getUsedNZCV(MICC);
2495 if (MIUsedNZCV.C || MIUsedNZCV.V)
2496 return false;
2497
2498 std::optional<UsedNZCV> NZCVUsedAfterCmp =
2499 examineCFlagsUse(MI, CmpInstr, TRI, &CCUseInstrs);
2500 // Condition flags are not used in CmpInstr basic block successors and only
2501 // Z or N flags allowed to be used after CmpInstr within its basic block
2502 if (!NZCVUsedAfterCmp || NZCVUsedAfterCmp->C || NZCVUsedAfterCmp->V)
2503 return false;
2504 // Z or N flag used after CmpInstr must correspond to the flag used in MI
2505 if ((MIUsedNZCV.Z && NZCVUsedAfterCmp->N) ||
2506 (MIUsedNZCV.N && NZCVUsedAfterCmp->Z))
2507 return false;
2508 // If CmpInstr is comparison to zero MI conditions are limited to eq, ne
2509 if (MIUsedNZCV.N && !CmpValue)
2510 return false;
2511
2512 // There must be no defs of flags between MI and CmpInstr
2513 if (areCFlagsAccessedBetweenInstrs(&MI, &CmpInstr, &TRI, AK_Write))
2514 return false;
2515
2516 // Condition code is inverted in the following cases:
2517 // 1. MI condition is ne; CmpInstr is 'ADDS %vreg, 0' or 'SUBS %vreg, 0'
2518 // 2. MI condition is eq, pl; CmpInstr is 'SUBS %vreg, 1'
2519 IsInvertCC = (CmpValue && (MICC == AArch64CC::EQ || MICC == AArch64CC::PL)) ||
2520 (!CmpValue && MICC == AArch64CC::NE);
2521 return true;
2522}
2523
2524/// Remove comparison in csinc-cmp sequence
2525///
2526/// Examples:
2527/// 1. \code
2528/// csinc w9, wzr, wzr, ne
2529/// cmp w9, #0
2530/// b.eq
2531/// \endcode
2532/// to
2533/// \code
2534/// csinc w9, wzr, wzr, ne
2535/// b.ne
2536/// \endcode
2537///
2538/// 2. \code
2539/// csinc x2, xzr, xzr, mi
2540/// cmp x2, #1
2541/// b.pl
2542/// \endcode
2543/// to
2544/// \code
2545/// csinc x2, xzr, xzr, mi
2546/// b.pl
2547/// \endcode
2548///
2549/// \param CmpInstr comparison instruction
2550/// \return True when comparison removed
2551bool AArch64InstrInfo::removeCmpToZeroOrOne(
2552 MachineInstr &CmpInstr, unsigned SrcReg, int CmpValue,
2553 const MachineRegisterInfo &MRI) const {
2554 MachineInstr *MI = MRI.getUniqueVRegDef(SrcReg);
2555 if (!MI)
2556 return false;
2557 const TargetRegisterInfo &TRI = getRegisterInfo();
2558 SmallVector<MachineInstr *, 4> CCUseInstrs;
2559 bool IsInvertCC = false;
2560 if (!canCmpInstrBeRemoved(*MI, CmpInstr, CmpValue, TRI, CCUseInstrs,
2561 IsInvertCC))
2562 return false;
2563 // Make transformation
2564 CmpInstr.eraseFromParent();
2565 if (IsInvertCC) {
2566 // Invert condition codes in CmpInstr CC users
2567 for (MachineInstr *CCUseInstr : CCUseInstrs) {
2568 int Idx = findCondCodeUseOperandIdxForBranchOrSelect(*CCUseInstr);
2569 assert(Idx >= 0 && "Unexpected instruction using CC.");
2570 MachineOperand &CCOperand = CCUseInstr->getOperand(Idx);
2572 static_cast<AArch64CC::CondCode>(CCOperand.getImm()));
2573 CCOperand.setImm(CCUse);
2574 }
2575 }
2576 return true;
2577}
2578
2579bool AArch64InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
2580 if (MI.getOpcode() != TargetOpcode::LOAD_STACK_GUARD &&
2581 MI.getOpcode() != AArch64::CATCHRET &&
2582 MI.getOpcode() != AArch64::STACK_GUARD_UNMIX)
2583 return false;
2584
2585 MachineBasicBlock &MBB = *MI.getParent();
2586 auto &Subtarget = MBB.getParent()->getSubtarget<AArch64Subtarget>();
2587 auto TRI = Subtarget.getRegisterInfo();
2588 DebugLoc DL = MI.getDebugLoc();
2589
2590 if (MI.getOpcode() == AArch64::STACK_GUARD_UNMIX) {
2591 // Expand STACK_GUARD_UNMIX to: sub Rd, fp, Rs
2592 // This computes FP - stored_mixed_value to unmix the cookie
2593 Register DstReg = MI.getOperand(0).getReg();
2594 Register SrcReg = MI.getOperand(1).getReg();
2595
2596 BuildMI(MBB, MI, DL, get(AArch64::SUBXrr), DstReg)
2597 .addReg(AArch64::FP)
2598 .addReg(SrcReg);
2599
2600 MBB.erase(MI);
2601 return true;
2602 }
2603
2604 if (MI.getOpcode() == AArch64::CATCHRET) {
2605 // Skip to the first instruction before the epilog.
2606 const TargetInstrInfo *TII =
2608 MachineBasicBlock *TargetMBB = MI.getOperand(0).getMBB();
2610 MachineBasicBlock::iterator FirstEpilogSEH = std::prev(MBBI);
2611 while (FirstEpilogSEH->getFlag(MachineInstr::FrameDestroy) &&
2612 FirstEpilogSEH != MBB.begin())
2613 FirstEpilogSEH = std::prev(FirstEpilogSEH);
2614 if (FirstEpilogSEH != MBB.begin())
2615 FirstEpilogSEH = std::next(FirstEpilogSEH);
2616 BuildMI(MBB, FirstEpilogSEH, DL, TII->get(AArch64::ADRP))
2617 .addReg(AArch64::X0, RegState::Define)
2618 .addMBB(TargetMBB, AArch64II::MO_PAGE);
2619 BuildMI(MBB, FirstEpilogSEH, DL, TII->get(AArch64::ADDXri))
2620 .addReg(AArch64::X0, RegState::Define)
2621 .addReg(AArch64::X0)
2623 .addImm(0);
2624 TargetMBB->setMachineBlockAddressTaken();
2625 return true;
2626 }
2627
2628 Register Reg = MI.getOperand(0).getReg();
2630 if (M.getStackProtectorGuard() == "sysreg") {
2631 const AArch64SysReg::SysReg *SrcReg =
2632 AArch64SysReg::lookupSysRegByName(M.getStackProtectorGuardReg());
2633 if (!SrcReg)
2634 report_fatal_error("Unknown SysReg for Stack Protector Guard Register");
2635
2636 // mrs xN, sysreg
2637 BuildMI(MBB, MI, DL, get(AArch64::MRS))
2639 .addImm(SrcReg->Encoding);
2640 int Offset = M.getStackProtectorGuardOffset();
2641 if (Offset >= 0 && Offset <= 32760 && Offset % 8 == 0) {
2642 // ldr xN, [xN, #offset]
2643 BuildMI(MBB, MI, DL, get(AArch64::LDRXui))
2644 .addDef(Reg)
2646 .addImm(Offset / 8);
2647 } else if (Offset >= -256 && Offset <= 255) {
2648 // ldur xN, [xN, #offset]
2649 BuildMI(MBB, MI, DL, get(AArch64::LDURXi))
2650 .addDef(Reg)
2652 .addImm(Offset);
2653 } else if (Offset >= -4095 && Offset <= 4095) {
2654 if (Offset > 0) {
2655 // add xN, xN, #offset
2656 BuildMI(MBB, MI, DL, get(AArch64::ADDXri))
2657 .addDef(Reg)
2659 .addImm(Offset)
2660 .addImm(0);
2661 } else {
2662 // sub xN, xN, #offset
2663 BuildMI(MBB, MI, DL, get(AArch64::SUBXri))
2664 .addDef(Reg)
2666 .addImm(-Offset)
2667 .addImm(0);
2668 }
2669 // ldr xN, [xN]
2670 BuildMI(MBB, MI, DL, get(AArch64::LDRXui))
2671 .addDef(Reg)
2673 .addImm(0);
2674 } else {
2675 // Cases that are larger than +/- 4095 and not a multiple of 8, or larger
2676 // than 23760.
2677 // It might be nice to use AArch64::MOVi32imm here, which would get
2678 // expanded in PreSched2 after PostRA, but our lone scratch Reg already
2679 // contains the MRS result. findScratchNonCalleeSaveRegister() in
2680 // AArch64FrameLowering might help us find such a scratch register
2681 // though. If we failed to find a scratch register, we could emit a
2682 // stream of add instructions to build up the immediate. Or, we could try
2683 // to insert a AArch64::MOVi32imm before register allocation so that we
2684 // didn't need to scavenge for a scratch register.
2685 report_fatal_error("Unable to encode Stack Protector Guard Offset");
2686 }
2687 MBB.erase(MI);
2688 return true;
2689 }
2690
2691 const GlobalValue *GV =
2692 cast<GlobalValue>((*MI.memoperands_begin())->getValue());
2693 const TargetMachine &TM = MBB.getParent()->getTarget();
2694 unsigned OpFlags = Subtarget.ClassifyGlobalReference(GV, TM);
2695 const unsigned char MO_NC = AArch64II::MO_NC;
2696
2697 unsigned GuardWidth = M.getStackProtectorGuardValueWidth().value_or(
2698 Subtarget.isTargetILP32() ? 4 : 8);
2699 if (GuardWidth != 4 && GuardWidth != 8)
2700 report_fatal_error("Unsupported stack protector value width");
2701 if ((OpFlags & AArch64II::MO_GOT) != 0) {
2702 BuildMI(MBB, MI, DL, get(AArch64::LOADgot), Reg)
2703 .addGlobalAddress(GV, 0, OpFlags);
2704 if (GuardWidth == 4) {
2705 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2706 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2707 .addDef(Reg32)
2709 .addImm(0)
2710 .addMemOperand(*MI.memoperands_begin())
2712 } else {
2713 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2715 .addImm(0)
2716 .addMemOperand(*MI.memoperands_begin());
2717 }
2718 } else if (TM.getCodeModel() == CodeModel::Large) {
2719 BuildMI(MBB, MI, DL, get(AArch64::MOVZXi), Reg)
2720 .addGlobalAddress(GV, 0, AArch64II::MO_G0 | MO_NC)
2721 .addImm(0);
2722 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2724 .addGlobalAddress(GV, 0, AArch64II::MO_G1 | MO_NC)
2725 .addImm(16);
2726 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2728 .addGlobalAddress(GV, 0, AArch64II::MO_G2 | MO_NC)
2729 .addImm(32);
2730 BuildMI(MBB, MI, DL, get(AArch64::MOVKXi), Reg)
2733 .addImm(48);
2734 if (GuardWidth == 4) {
2735 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2736 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2737 .addDef(Reg32)
2739 .addImm(0)
2740 .addMemOperand(*MI.memoperands_begin())
2742 } else {
2743 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2745 .addImm(0)
2746 .addMemOperand(*MI.memoperands_begin());
2747 }
2748 } else {
2749 BuildMI(MBB, MI, DL, get(AArch64::ADRP), Reg)
2750 .addGlobalAddress(GV, 0, OpFlags | AArch64II::MO_PAGE);
2751 unsigned char LoFlags = OpFlags | AArch64II::MO_PAGEOFF | MO_NC;
2752 if (GuardWidth == 4) {
2753 unsigned Reg32 = TRI->getSubReg(Reg, AArch64::sub_32);
2754 BuildMI(MBB, MI, DL, get(AArch64::LDRWui))
2755 .addDef(Reg32)
2757 .addGlobalAddress(GV, 0, LoFlags)
2758 .addMemOperand(*MI.memoperands_begin())
2760 } else {
2761 BuildMI(MBB, MI, DL, get(AArch64::LDRXui), Reg)
2763 .addGlobalAddress(GV, 0, LoFlags)
2764 .addMemOperand(*MI.memoperands_begin());
2765 }
2766 }
2767 // To match MSVC. Unlike x86_64 which uses xor instruction to mix the cookie,
2768 // we use sub instruction to mix the cookie on aarch64.
2769 // The mixing happens here in expandPostRAPseudo (after RA) to ensure we use
2770 // the final frame pointer value.
2771 if (Subtarget.getTargetTriple().isOSMSVCRT())
2772 BuildMI(MBB, MI, DL, get(AArch64::SUBXrr), Reg)
2773 .addReg(AArch64::FP)
2775
2776 MBB.erase(MI);
2777
2778 return true;
2779}
2780
2781// Return true if this instruction simply sets its single destination register
2782// to zero. This is equivalent to a register rename of the zero-register.
2784 switch (MI.getOpcode()) {
2785 default:
2786 break;
2787 case AArch64::MOVZWi:
2788 case AArch64::MOVZXi: // movz Rd, #0 (LSL #0)
2789 if (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) {
2790 assert(MI.getDesc().getNumOperands() == 3 &&
2791 MI.getOperand(2).getImm() == 0 && "invalid MOVZi operands");
2792 return true;
2793 }
2794 break;
2795 case AArch64::ANDWri: // and Rd, Rzr, #imm
2796 return MI.getOperand(1).getReg() == AArch64::WZR;
2797 case AArch64::ANDXri:
2798 return MI.getOperand(1).getReg() == AArch64::XZR;
2799 case TargetOpcode::COPY:
2800 return MI.getOperand(1).getReg() == AArch64::WZR;
2801 }
2802 return false;
2803}
2804
2805// Return true if this instruction simply renames a general register without
2806// modifying bits.
2808 switch (MI.getOpcode()) {
2809 default:
2810 break;
2811 case TargetOpcode::COPY: {
2812 // GPR32 copies will by lowered to ORRXrs
2813 Register DstReg = MI.getOperand(0).getReg();
2814 return (AArch64::GPR32RegClass.contains(DstReg) ||
2815 AArch64::GPR64RegClass.contains(DstReg));
2816 }
2817 case AArch64::ORRXrs: // orr Xd, Xzr, Xm (LSL #0)
2818 if (MI.getOperand(1).getReg() == AArch64::XZR) {
2819 assert(MI.getDesc().getNumOperands() == 4 &&
2820 MI.getOperand(3).getImm() == 0 && "invalid ORRrs operands");
2821 return true;
2822 }
2823 break;
2824 case AArch64::ADDXri: // add Xd, Xn, #0 (LSL #0)
2825 if (MI.getOperand(2).getImm() == 0) {
2826 assert(MI.getDesc().getNumOperands() == 4 &&
2827 MI.getOperand(3).getImm() == 0 && "invalid ADDXri operands");
2828 return true;
2829 }
2830 break;
2831 }
2832 return false;
2833}
2834
2835// Return true if this instruction simply renames a general register without
2836// modifying bits.
2838 switch (MI.getOpcode()) {
2839 default:
2840 break;
2841 case TargetOpcode::COPY: {
2842 Register DstReg = MI.getOperand(0).getReg();
2843 return AArch64::FPR128RegClass.contains(DstReg);
2844 }
2845 case AArch64::ORRv16i8:
2846 if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) {
2847 assert(MI.getDesc().getNumOperands() == 3 && MI.getOperand(0).isReg() &&
2848 "invalid ORRv16i8 operands");
2849 return true;
2850 }
2851 break;
2852 }
2853 return false;
2854}
2855
2856static bool isFrameLoadOpcode(int Opcode) {
2857 switch (Opcode) {
2858 default:
2859 return false;
2860 case AArch64::LDRWui:
2861 case AArch64::LDRXui:
2862 case AArch64::LDRBui:
2863 case AArch64::LDRHui:
2864 case AArch64::LDRSui:
2865 case AArch64::LDRDui:
2866 case AArch64::LDRQui:
2867 case AArch64::LDR_PXI:
2868 return true;
2869 }
2870}
2871
2873 int &FrameIndex) const {
2874 if (!isFrameLoadOpcode(MI.getOpcode()))
2875 return Register();
2876
2877 if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
2878 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
2879 FrameIndex = MI.getOperand(1).getIndex();
2880 return MI.getOperand(0).getReg();
2881 }
2882 return Register();
2883}
2884
2885static bool isFrameStoreOpcode(int Opcode) {
2886 switch (Opcode) {
2887 default:
2888 return false;
2889 case AArch64::STRWui:
2890 case AArch64::STRXui:
2891 case AArch64::STRBui:
2892 case AArch64::STRHui:
2893 case AArch64::STRSui:
2894 case AArch64::STRDui:
2895 case AArch64::STRQui:
2896 case AArch64::STR_PXI:
2897 return true;
2898 }
2899}
2900
2902 int &FrameIndex) const {
2903 if (!isFrameStoreOpcode(MI.getOpcode()))
2904 return Register();
2905
2906 if (MI.getOperand(0).getSubReg() == 0 && MI.getOperand(1).isFI() &&
2907 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0) {
2908 FrameIndex = MI.getOperand(1).getIndex();
2909 return MI.getOperand(0).getReg();
2910 }
2911 return Register();
2912}
2913
2915 int &FrameIndex) const {
2916 if (!isFrameStoreOpcode(MI.getOpcode()))
2917 return Register();
2918
2919 if (Register Reg = isStoreToStackSlot(MI, FrameIndex))
2920 return Reg;
2921
2923 if (hasStoreToStackSlot(MI, Accesses)) {
2924 if (Accesses.size() > 1)
2925 return Register();
2926
2927 FrameIndex =
2928 cast<FixedStackPseudoSourceValue>(Accesses.front()->getPseudoValue())
2929 ->getFrameIndex();
2930 return MI.getOperand(0).getReg();
2931 }
2932 return Register();
2933}
2934
2936 int &FrameIndex) const {
2937 if (!isFrameLoadOpcode(MI.getOpcode()))
2938 return Register();
2939
2940 if (Register Reg = isLoadFromStackSlot(MI, FrameIndex))
2941 return Reg;
2942
2944 if (hasLoadFromStackSlot(MI, Accesses)) {
2945 if (Accesses.size() > 1)
2946 return Register();
2947
2948 FrameIndex =
2949 cast<FixedStackPseudoSourceValue>(Accesses.front()->getPseudoValue())
2950 ->getFrameIndex();
2951 return MI.getOperand(0).getReg();
2952 }
2953 return Register();
2954}
2955
2956/// Check all MachineMemOperands for a hint to suppress pairing.
2958 return llvm::any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
2959 return MMO->getFlags() & MOSuppressPair;
2960 });
2961}
2962
2963/// Set a flag on the first MachineMemOperand to suppress pairing.
2965 if (MI.memoperands_empty())
2966 return;
2967 (*MI.memoperands_begin())->setFlags(MOSuppressPair);
2968}
2969
2970/// Check all MachineMemOperands for a hint that the load/store is strided.
2972 return llvm::any_of(MI.memoperands(), [](MachineMemOperand *MMO) {
2973 return MMO->getFlags() & MOStridedAccess;
2974 });
2975}
2976
2978 switch (Opc) {
2979 default:
2980 return false;
2981 case AArch64::STURSi:
2982 case AArch64::STRSpre:
2983 case AArch64::STURDi:
2984 case AArch64::STRDpre:
2985 case AArch64::STURQi:
2986 case AArch64::STRQpre:
2987 case AArch64::STURBBi:
2988 case AArch64::STURHHi:
2989 case AArch64::STURWi:
2990 case AArch64::STRWpre:
2991 case AArch64::STURXi:
2992 case AArch64::STRXpre:
2993 case AArch64::LDURSi:
2994 case AArch64::LDRSpre:
2995 case AArch64::LDURDi:
2996 case AArch64::LDRDpre:
2997 case AArch64::LDURQi:
2998 case AArch64::LDRQpre:
2999 case AArch64::LDURWi:
3000 case AArch64::LDRWpre:
3001 case AArch64::LDURXi:
3002 case AArch64::LDRXpre:
3003 case AArch64::LDRSWpre:
3004 case AArch64::LDURSWi:
3005 case AArch64::LDURHHi:
3006 case AArch64::LDURBBi:
3007 case AArch64::LDURSBWi:
3008 case AArch64::LDURSHWi:
3009 return true;
3010 }
3011}
3012
3013std::optional<unsigned> AArch64InstrInfo::getUnscaledLdSt(unsigned Opc) {
3014 switch (Opc) {
3015 default: return {};
3016 case AArch64::PRFMui: return AArch64::PRFUMi;
3017 case AArch64::LDRXui: return AArch64::LDURXi;
3018 case AArch64::LDRWui: return AArch64::LDURWi;
3019 case AArch64::LDRBui: return AArch64::LDURBi;
3020 case AArch64::LDRHui: return AArch64::LDURHi;
3021 case AArch64::LDRSui: return AArch64::LDURSi;
3022 case AArch64::LDRDui: return AArch64::LDURDi;
3023 case AArch64::LDRQui: return AArch64::LDURQi;
3024 case AArch64::LDRBBui: return AArch64::LDURBBi;
3025 case AArch64::LDRHHui: return AArch64::LDURHHi;
3026 case AArch64::LDRSBXui: return AArch64::LDURSBXi;
3027 case AArch64::LDRSBWui: return AArch64::LDURSBWi;
3028 case AArch64::LDRSHXui: return AArch64::LDURSHXi;
3029 case AArch64::LDRSHWui: return AArch64::LDURSHWi;
3030 case AArch64::LDRSWui: return AArch64::LDURSWi;
3031 case AArch64::STRXui: return AArch64::STURXi;
3032 case AArch64::STRWui: return AArch64::STURWi;
3033 case AArch64::STRBui: return AArch64::STURBi;
3034 case AArch64::STRHui: return AArch64::STURHi;
3035 case AArch64::STRSui: return AArch64::STURSi;
3036 case AArch64::STRDui: return AArch64::STURDi;
3037 case AArch64::STRQui: return AArch64::STURQi;
3038 case AArch64::STRBBui: return AArch64::STURBBi;
3039 case AArch64::STRHHui: return AArch64::STURHHi;
3040 }
3041}
3042
3044 switch (Opc) {
3045 default:
3046 llvm_unreachable("Unhandled Opcode in getLoadStoreImmIdx");
3047 case AArch64::ADDG:
3048 case AArch64::LDAPURBi:
3049 case AArch64::LDAPURHi:
3050 case AArch64::LDAPURi:
3051 case AArch64::LDAPURSBWi:
3052 case AArch64::LDAPURSBXi:
3053 case AArch64::LDAPURSHWi:
3054 case AArch64::LDAPURSHXi:
3055 case AArch64::LDAPURSWi:
3056 case AArch64::LDAPURXi:
3057 case AArch64::LDR_PPXI:
3058 case AArch64::LDR_PXI:
3059 case AArch64::LDR_ZXI:
3060 case AArch64::LDR_ZZXI:
3061 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
3062 case AArch64::LDR_ZZZXI:
3063 case AArch64::LDR_ZZZZXI:
3064 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
3065 case AArch64::LDRBBui:
3066 case AArch64::LDRBui:
3067 case AArch64::LDRDui:
3068 case AArch64::LDRHHui:
3069 case AArch64::LDRHui:
3070 case AArch64::LDRQui:
3071 case AArch64::LDRSBWui:
3072 case AArch64::LDRSBXui:
3073 case AArch64::LDRSHWui:
3074 case AArch64::LDRSHXui:
3075 case AArch64::LDRSui:
3076 case AArch64::LDRSWui:
3077 case AArch64::LDRWui:
3078 case AArch64::LDRXui:
3079 case AArch64::LDURBBi:
3080 case AArch64::LDURBi:
3081 case AArch64::LDURDi:
3082 case AArch64::LDURHHi:
3083 case AArch64::LDURHi:
3084 case AArch64::LDURQi:
3085 case AArch64::LDURSBWi:
3086 case AArch64::LDURSBXi:
3087 case AArch64::LDURSHWi:
3088 case AArch64::LDURSHXi:
3089 case AArch64::LDURSi:
3090 case AArch64::LDURSWi:
3091 case AArch64::LDURWi:
3092 case AArch64::LDURXi:
3093 case AArch64::PRFMui:
3094 case AArch64::PRFUMi:
3095 case AArch64::ST2Gi:
3096 case AArch64::STGi:
3097 case AArch64::STLURBi:
3098 case AArch64::STLURHi:
3099 case AArch64::STLURWi:
3100 case AArch64::STLURXi:
3101 case AArch64::StoreSwiftAsyncContext:
3102 case AArch64::STR_PPXI:
3103 case AArch64::STR_PXI:
3104 case AArch64::STR_ZXI:
3105 case AArch64::STR_ZZXI:
3106 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
3107 case AArch64::STR_ZZZXI:
3108 case AArch64::STR_ZZZZXI:
3109 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
3110 case AArch64::STRBBui:
3111 case AArch64::STRBui:
3112 case AArch64::STRDui:
3113 case AArch64::STRHHui:
3114 case AArch64::STRHui:
3115 case AArch64::STRQui:
3116 case AArch64::STRSui:
3117 case AArch64::STRWui:
3118 case AArch64::STRXui:
3119 case AArch64::STURBBi:
3120 case AArch64::STURBi:
3121 case AArch64::STURDi:
3122 case AArch64::STURHHi:
3123 case AArch64::STURHi:
3124 case AArch64::STURQi:
3125 case AArch64::STURSi:
3126 case AArch64::STURWi:
3127 case AArch64::STURXi:
3128 case AArch64::STZ2Gi:
3129 case AArch64::STZGi:
3130 case AArch64::TAGPstack:
3131 case AArch64::ATOMIC_STORE_HINT_Bi:
3132 case AArch64::ATOMIC_STORE_HINT_Hi:
3133 case AArch64::ATOMIC_STORE_HINT_Wi:
3134 case AArch64::ATOMIC_STORE_HINT_Si:
3135 case AArch64::ATOMIC_STORE_HINT_Xi:
3136 case AArch64::ATOMIC_STORE_HINT_Di:
3137 case AArch64::ATOMIC_STORE_HINT_Bui:
3138 case AArch64::ATOMIC_STORE_HINT_Hui:
3139 case AArch64::ATOMIC_STORE_HINT_Wui:
3140 case AArch64::ATOMIC_STORE_HINT_Sui:
3141 case AArch64::ATOMIC_STORE_HINT_Xui:
3142 case AArch64::ATOMIC_STORE_HINT_Dui:
3143 return 2;
3144 case AArch64::LD1B_D_IMM:
3145 case AArch64::LD1B_H_IMM:
3146 case AArch64::LD1B_IMM:
3147 case AArch64::LD1B_S_IMM:
3148 case AArch64::LD1D_IMM:
3149 case AArch64::LD1H_D_IMM:
3150 case AArch64::LD1H_IMM:
3151 case AArch64::LD1H_S_IMM:
3152 case AArch64::LD1RB_D_IMM:
3153 case AArch64::LD1RB_H_IMM:
3154 case AArch64::LD1RB_IMM:
3155 case AArch64::LD1RB_S_IMM:
3156 case AArch64::LD1RD_IMM:
3157 case AArch64::LD1RH_D_IMM:
3158 case AArch64::LD1RH_IMM:
3159 case AArch64::LD1RH_S_IMM:
3160 case AArch64::LD1RSB_D_IMM:
3161 case AArch64::LD1RSB_H_IMM:
3162 case AArch64::LD1RSB_S_IMM:
3163 case AArch64::LD1RSH_D_IMM:
3164 case AArch64::LD1RSH_S_IMM:
3165 case AArch64::LD1RSW_IMM:
3166 case AArch64::LD1RW_D_IMM:
3167 case AArch64::LD1RW_IMM:
3168 case AArch64::LD1SB_D_IMM:
3169 case AArch64::LD1SB_H_IMM:
3170 case AArch64::LD1SB_S_IMM:
3171 case AArch64::LD1SH_D_IMM:
3172 case AArch64::LD1SH_S_IMM:
3173 case AArch64::LD1SW_D_IMM:
3174 case AArch64::LD1W_D_IMM:
3175 case AArch64::LD1W_IMM:
3176 case AArch64::LD2B_IMM:
3177 case AArch64::LD2D_IMM:
3178 case AArch64::LD2H_IMM:
3179 case AArch64::LD2W_IMM:
3180 case AArch64::LD3B_IMM:
3181 case AArch64::LD3D_IMM:
3182 case AArch64::LD3H_IMM:
3183 case AArch64::LD3W_IMM:
3184 case AArch64::LD4B_IMM:
3185 case AArch64::LD4D_IMM:
3186 case AArch64::LD4H_IMM:
3187 case AArch64::LD4W_IMM:
3188 case AArch64::LDG:
3189 case AArch64::LDNF1B_D_IMM:
3190 case AArch64::LDNF1B_H_IMM:
3191 case AArch64::LDNF1B_IMM:
3192 case AArch64::LDNF1B_S_IMM:
3193 case AArch64::LDNF1D_IMM:
3194 case AArch64::LDNF1H_D_IMM:
3195 case AArch64::LDNF1H_IMM:
3196 case AArch64::LDNF1H_S_IMM:
3197 case AArch64::LDNF1SB_D_IMM:
3198 case AArch64::LDNF1SB_H_IMM:
3199 case AArch64::LDNF1SB_S_IMM:
3200 case AArch64::LDNF1SH_D_IMM:
3201 case AArch64::LDNF1SH_S_IMM:
3202 case AArch64::LDNF1SW_D_IMM:
3203 case AArch64::LDNF1W_D_IMM:
3204 case AArch64::LDNF1W_IMM:
3205 case AArch64::LDNPDi:
3206 case AArch64::LDNPQi:
3207 case AArch64::LDNPSi:
3208 case AArch64::LDNPWi:
3209 case AArch64::LDNPXi:
3210 case AArch64::LDNT1B_ZRI:
3211 case AArch64::LDNT1D_ZRI:
3212 case AArch64::LDNT1H_ZRI:
3213 case AArch64::LDNT1W_ZRI:
3214 case AArch64::LDPDi:
3215 case AArch64::LDPQi:
3216 case AArch64::LDPSi:
3217 case AArch64::LDPWi:
3218 case AArch64::LDPXi:
3219 case AArch64::LDRBBpost:
3220 case AArch64::LDRBBpre:
3221 case AArch64::LDRBpost:
3222 case AArch64::LDRBpre:
3223 case AArch64::LDRDpost:
3224 case AArch64::LDRDpre:
3225 case AArch64::LDRHHpost:
3226 case AArch64::LDRHHpre:
3227 case AArch64::LDRHpost:
3228 case AArch64::LDRHpre:
3229 case AArch64::LDRQpost:
3230 case AArch64::LDRQpre:
3231 case AArch64::LDRSpost:
3232 case AArch64::LDRSpre:
3233 case AArch64::LDRWpost:
3234 case AArch64::LDRWpre:
3235 case AArch64::LDRXpost:
3236 case AArch64::LDRXpre:
3237 case AArch64::ST1B_D_IMM:
3238 case AArch64::ST1B_H_IMM:
3239 case AArch64::ST1B_IMM:
3240 case AArch64::ST1B_S_IMM:
3241 case AArch64::ST1D_IMM:
3242 case AArch64::ST1H_D_IMM:
3243 case AArch64::ST1H_IMM:
3244 case AArch64::ST1H_S_IMM:
3245 case AArch64::ST1W_D_IMM:
3246 case AArch64::ST1W_IMM:
3247 case AArch64::ST2B_IMM:
3248 case AArch64::ST2D_IMM:
3249 case AArch64::ST2H_IMM:
3250 case AArch64::ST2W_IMM:
3251 case AArch64::ST3B_IMM:
3252 case AArch64::ST3D_IMM:
3253 case AArch64::ST3H_IMM:
3254 case AArch64::ST3W_IMM:
3255 case AArch64::ST4B_IMM:
3256 case AArch64::ST4D_IMM:
3257 case AArch64::ST4H_IMM:
3258 case AArch64::ST4W_IMM:
3259 case AArch64::STGPi:
3260 case AArch64::STGPreIndex:
3261 case AArch64::STZGPreIndex:
3262 case AArch64::ST2GPreIndex:
3263 case AArch64::STZ2GPreIndex:
3264 case AArch64::STGPostIndex:
3265 case AArch64::STZGPostIndex:
3266 case AArch64::ST2GPostIndex:
3267 case AArch64::STZ2GPostIndex:
3268 case AArch64::STNPDi:
3269 case AArch64::STNPQi:
3270 case AArch64::STNPSi:
3271 case AArch64::STNPWi:
3272 case AArch64::STNPXi:
3273 case AArch64::STNT1B_ZRI:
3274 case AArch64::STNT1D_ZRI:
3275 case AArch64::STNT1H_ZRI:
3276 case AArch64::STNT1W_ZRI:
3277 case AArch64::STPDi:
3278 case AArch64::STPQi:
3279 case AArch64::STPSi:
3280 case AArch64::STPWi:
3281 case AArch64::STPXi:
3282 case AArch64::STRBBpost:
3283 case AArch64::STRBBpre:
3284 case AArch64::STRBpost:
3285 case AArch64::STRBpre:
3286 case AArch64::STRDpost:
3287 case AArch64::STRDpre:
3288 case AArch64::STRHHpost:
3289 case AArch64::STRHHpre:
3290 case AArch64::STRHpost:
3291 case AArch64::STRHpre:
3292 case AArch64::STRQpost:
3293 case AArch64::STRQpre:
3294 case AArch64::STRSpost:
3295 case AArch64::STRSpre:
3296 case AArch64::STRWpost:
3297 case AArch64::STRWpre:
3298 case AArch64::STRXpost:
3299 case AArch64::STRXpre:
3300 case AArch64::LD1B_2Z_IMM:
3301 case AArch64::LD1B_2Z_STRIDED_IMM:
3302 case AArch64::LD1H_2Z_IMM:
3303 case AArch64::LD1H_2Z_STRIDED_IMM:
3304 case AArch64::LD1W_2Z_IMM:
3305 case AArch64::LD1W_2Z_STRIDED_IMM:
3306 case AArch64::LD1D_2Z_IMM:
3307 case AArch64::LD1D_2Z_STRIDED_IMM:
3308 case AArch64::LD1B_4Z_IMM:
3309 case AArch64::LD1B_4Z_STRIDED_IMM:
3310 case AArch64::LD1H_4Z_IMM:
3311 case AArch64::LD1H_4Z_STRIDED_IMM:
3312 case AArch64::LD1W_4Z_IMM:
3313 case AArch64::LD1W_4Z_STRIDED_IMM:
3314 case AArch64::LD1D_4Z_IMM:
3315 case AArch64::LD1D_4Z_STRIDED_IMM:
3316 case AArch64::LD1B_2Z_IMM_PSEUDO:
3317 case AArch64::LD1H_2Z_IMM_PSEUDO:
3318 case AArch64::LD1W_2Z_IMM_PSEUDO:
3319 case AArch64::LD1D_2Z_IMM_PSEUDO:
3320 case AArch64::LD1B_4Z_IMM_PSEUDO:
3321 case AArch64::LD1H_4Z_IMM_PSEUDO:
3322 case AArch64::LD1W_4Z_IMM_PSEUDO:
3323 case AArch64::LD1D_4Z_IMM_PSEUDO:
3324 case AArch64::ST1B_2Z_IMM:
3325 case AArch64::ST1B_2Z_STRIDED_IMM:
3326 case AArch64::ST1H_2Z_IMM:
3327 case AArch64::ST1H_2Z_STRIDED_IMM:
3328 case AArch64::ST1W_2Z_IMM:
3329 case AArch64::ST1W_2Z_STRIDED_IMM:
3330 case AArch64::ST1D_2Z_IMM:
3331 case AArch64::ST1D_2Z_STRIDED_IMM:
3332 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
3333 case AArch64::LDNT1B_2Z_IMM:
3334 case AArch64::LDNT1B_2Z_STRIDED_IMM:
3335 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
3336 case AArch64::LDNT1H_2Z_IMM:
3337 case AArch64::LDNT1H_2Z_STRIDED_IMM:
3338 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
3339 case AArch64::LDNT1W_2Z_IMM:
3340 case AArch64::LDNT1W_2Z_STRIDED_IMM:
3341 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
3342 case AArch64::LDNT1D_2Z_IMM:
3343 case AArch64::LDNT1D_2Z_STRIDED_IMM:
3344 case AArch64::STNT1B_2Z_IMM:
3345 case AArch64::STNT1B_2Z_STRIDED_IMM:
3346 case AArch64::STNT1H_2Z_IMM:
3347 case AArch64::STNT1H_2Z_STRIDED_IMM:
3348 case AArch64::STNT1W_2Z_IMM:
3349 case AArch64::STNT1W_2Z_STRIDED_IMM:
3350 case AArch64::STNT1D_2Z_IMM:
3351 case AArch64::STNT1D_2Z_STRIDED_IMM:
3352 case AArch64::ST1B_2Z_IMM_PSEUDO:
3353 case AArch64::ST1H_2Z_IMM_PSEUDO:
3354 case AArch64::ST1W_2Z_IMM_PSEUDO:
3355 case AArch64::ST1D_2Z_IMM_PSEUDO:
3356 case AArch64::STNT1B_2Z_IMM_PSEUDO:
3357 case AArch64::STNT1H_2Z_IMM_PSEUDO:
3358 case AArch64::STNT1W_2Z_IMM_PSEUDO:
3359 case AArch64::STNT1D_2Z_IMM_PSEUDO:
3360 case AArch64::ST1B_4Z_IMM:
3361 case AArch64::ST1B_4Z_STRIDED_IMM:
3362 case AArch64::ST1H_4Z_IMM:
3363 case AArch64::ST1H_4Z_STRIDED_IMM:
3364 case AArch64::ST1W_4Z_IMM:
3365 case AArch64::ST1W_4Z_STRIDED_IMM:
3366 case AArch64::ST1D_4Z_IMM:
3367 case AArch64::ST1D_4Z_STRIDED_IMM:
3368 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
3369 case AArch64::LDNT1B_4Z_IMM:
3370 case AArch64::LDNT1B_4Z_STRIDED_IMM:
3371 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
3372 case AArch64::LDNT1H_4Z_IMM:
3373 case AArch64::LDNT1H_4Z_STRIDED_IMM:
3374 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
3375 case AArch64::LDNT1W_4Z_IMM:
3376 case AArch64::LDNT1W_4Z_STRIDED_IMM:
3377 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
3378 case AArch64::LDNT1D_4Z_IMM:
3379 case AArch64::LDNT1D_4Z_STRIDED_IMM:
3380 case AArch64::STNT1B_4Z_IMM:
3381 case AArch64::STNT1B_4Z_STRIDED_IMM:
3382 case AArch64::STNT1H_4Z_IMM:
3383 case AArch64::STNT1H_4Z_STRIDED_IMM:
3384 case AArch64::STNT1W_4Z_IMM:
3385 case AArch64::STNT1W_4Z_STRIDED_IMM:
3386 case AArch64::STNT1D_4Z_IMM:
3387 case AArch64::STNT1D_4Z_STRIDED_IMM:
3388 case AArch64::ST1B_4Z_IMM_PSEUDO:
3389 case AArch64::ST1H_4Z_IMM_PSEUDO:
3390 case AArch64::ST1W_4Z_IMM_PSEUDO:
3391 case AArch64::ST1D_4Z_IMM_PSEUDO:
3392 case AArch64::STNT1B_4Z_IMM_PSEUDO:
3393 case AArch64::STNT1H_4Z_IMM_PSEUDO:
3394 case AArch64::STNT1W_4Z_IMM_PSEUDO:
3395 case AArch64::STNT1D_4Z_IMM_PSEUDO:
3396 return 3;
3397 case AArch64::LDPDpost:
3398 case AArch64::LDPDpre:
3399 case AArch64::LDPQpost:
3400 case AArch64::LDPQpre:
3401 case AArch64::LDPSpost:
3402 case AArch64::LDPSpre:
3403 case AArch64::LDPWpost:
3404 case AArch64::LDPWpre:
3405 case AArch64::LDPXpost:
3406 case AArch64::LDPXpre:
3407 case AArch64::STGPpre:
3408 case AArch64::STGPpost:
3409 case AArch64::STPDpost:
3410 case AArch64::STPDpre:
3411 case AArch64::STPQpost:
3412 case AArch64::STPQpre:
3413 case AArch64::STPSpost:
3414 case AArch64::STPSpre:
3415 case AArch64::STPWpost:
3416 case AArch64::STPWpre:
3417 case AArch64::STPXpost:
3418 case AArch64::STPXpre:
3419 return 4;
3420 }
3421}
3422
3424 switch (MI.getOpcode()) {
3425 default:
3426 return false;
3427 // Scaled instructions.
3428 case AArch64::STRSui:
3429 case AArch64::STRDui:
3430 case AArch64::STRQui:
3431 case AArch64::STRXui:
3432 case AArch64::STRWui:
3433 case AArch64::LDRSui:
3434 case AArch64::LDRDui:
3435 case AArch64::LDRQui:
3436 case AArch64::LDRXui:
3437 case AArch64::LDRWui:
3438 case AArch64::LDRSWui:
3439 // Unscaled instructions.
3440 case AArch64::STURSi:
3441 case AArch64::STRSpre:
3442 case AArch64::STURDi:
3443 case AArch64::STRDpre:
3444 case AArch64::STURQi:
3445 case AArch64::STRQpre:
3446 case AArch64::STURWi:
3447 case AArch64::STRWpre:
3448 case AArch64::STURXi:
3449 case AArch64::STRXpre:
3450 case AArch64::LDURSi:
3451 case AArch64::LDRSpre:
3452 case AArch64::LDURDi:
3453 case AArch64::LDRDpre:
3454 case AArch64::LDURQi:
3455 case AArch64::LDRQpre:
3456 case AArch64::LDURWi:
3457 case AArch64::LDRWpre:
3458 case AArch64::LDURXi:
3459 case AArch64::LDRXpre:
3460 case AArch64::LDURSWi:
3461 case AArch64::LDRSWpre:
3462 // SVE instructions.
3463 case AArch64::LDR_ZXI:
3464 case AArch64::STR_ZXI:
3465 return true;
3466 }
3467}
3468
3470 switch (MI.getOpcode()) {
3471 default:
3472 assert((!MI.isCall() || !MI.isReturn()) &&
3473 "Unexpected instruction - was a new tail call opcode introduced?");
3474 return false;
3475 case AArch64::TCRETURNdi:
3476 case AArch64::TCRETURNri:
3477 case AArch64::TCRETURNrix16x17:
3478 case AArch64::TCRETURNrix17:
3479 case AArch64::TCRETURNrinotx16:
3480 case AArch64::TCRETURNriALL:
3481 case AArch64::AUTH_TCRETURN:
3482 case AArch64::AUTH_TCRETURN_BTI:
3483 return true;
3484 }
3485}
3486
3488 switch (Opc) {
3489 default:
3490 llvm_unreachable("Opcode has no flag setting equivalent!");
3491 // 32-bit cases:
3492 case AArch64::ADDWri:
3493 return AArch64::ADDSWri;
3494 case AArch64::ADDWrr:
3495 return AArch64::ADDSWrr;
3496 case AArch64::ADDWrs:
3497 return AArch64::ADDSWrs;
3498 case AArch64::ADDWrx:
3499 return AArch64::ADDSWrx;
3500 case AArch64::ANDWri:
3501 return AArch64::ANDSWri;
3502 case AArch64::ANDWrr:
3503 return AArch64::ANDSWrr;
3504 case AArch64::ANDWrs:
3505 return AArch64::ANDSWrs;
3506 case AArch64::BICWrr:
3507 return AArch64::BICSWrr;
3508 case AArch64::BICWrs:
3509 return AArch64::BICSWrs;
3510 case AArch64::SUBWri:
3511 return AArch64::SUBSWri;
3512 case AArch64::SUBWrr:
3513 return AArch64::SUBSWrr;
3514 case AArch64::SUBWrs:
3515 return AArch64::SUBSWrs;
3516 case AArch64::SUBWrx:
3517 return AArch64::SUBSWrx;
3518 // 64-bit cases:
3519 case AArch64::ADDXri:
3520 return AArch64::ADDSXri;
3521 case AArch64::ADDXrr:
3522 return AArch64::ADDSXrr;
3523 case AArch64::ADDXrs:
3524 return AArch64::ADDSXrs;
3525 case AArch64::ADDXrx:
3526 return AArch64::ADDSXrx;
3527 case AArch64::ANDXri:
3528 return AArch64::ANDSXri;
3529 case AArch64::ANDXrr:
3530 return AArch64::ANDSXrr;
3531 case AArch64::ANDXrs:
3532 return AArch64::ANDSXrs;
3533 case AArch64::BICXrr:
3534 return AArch64::BICSXrr;
3535 case AArch64::BICXrs:
3536 return AArch64::BICSXrs;
3537 case AArch64::SUBXri:
3538 return AArch64::SUBSXri;
3539 case AArch64::SUBXrr:
3540 return AArch64::SUBSXrr;
3541 case AArch64::SUBXrs:
3542 return AArch64::SUBSXrs;
3543 case AArch64::SUBXrx:
3544 return AArch64::SUBSXrx;
3545 // SVE instructions:
3546 case AArch64::AND_PPzPP:
3547 return AArch64::ANDS_PPzPP;
3548 case AArch64::BIC_PPzPP:
3549 return AArch64::BICS_PPzPP;
3550 case AArch64::EOR_PPzPP:
3551 return AArch64::EORS_PPzPP;
3552 case AArch64::NAND_PPzPP:
3553 return AArch64::NANDS_PPzPP;
3554 case AArch64::NOR_PPzPP:
3555 return AArch64::NORS_PPzPP;
3556 case AArch64::ORN_PPzPP:
3557 return AArch64::ORNS_PPzPP;
3558 case AArch64::ORR_PPzPP:
3559 return AArch64::ORRS_PPzPP;
3560 case AArch64::BRKA_PPzP:
3561 return AArch64::BRKAS_PPzP;
3562 case AArch64::BRKPA_PPzPP:
3563 return AArch64::BRKPAS_PPzPP;
3564 case AArch64::BRKB_PPzP:
3565 return AArch64::BRKBS_PPzP;
3566 case AArch64::BRKPB_PPzPP:
3567 return AArch64::BRKPBS_PPzPP;
3568 case AArch64::BRKN_PPzP:
3569 return AArch64::BRKNS_PPzP;
3570 case AArch64::RDFFR_PPz:
3571 return AArch64::RDFFRS_PPz;
3572 case AArch64::PTRUE_B:
3573 return AArch64::PTRUES_B;
3574 }
3575}
3576
3577// Is this a candidate for ld/st merging or pairing? For example, we don't
3578// touch volatiles or load/stores that have a hint to avoid pair formation.
3580
3581 bool IsPreLdSt = isPreLdSt(MI);
3582
3583 // If this is a volatile load/store, don't mess with it.
3584 if (MI.hasOrderedMemoryRef())
3585 return false;
3586
3587 // Make sure this is a reg/fi+imm (as opposed to an address reloc).
3588 // For Pre-inc LD/ST, the operand is shifted by one.
3589 assert((MI.getOperand(IsPreLdSt ? 2 : 1).isReg() ||
3590 MI.getOperand(IsPreLdSt ? 2 : 1).isFI()) &&
3591 "Expected a reg or frame index operand.");
3592
3593 // For Pre-indexed addressing quadword instructions, the third operand is the
3594 // immediate value.
3595 bool IsImmPreLdSt = IsPreLdSt && MI.getOperand(3).isImm();
3596
3597 if (!MI.getOperand(2).isImm() && !IsImmPreLdSt)
3598 return false;
3599
3600 // Can't merge/pair if the instruction modifies the base register.
3601 // e.g., ldr x0, [x0]
3602 // This case will never occur with an FI base.
3603 // However, if the instruction is an LDR<S,D,Q,W,X,SW>pre or
3604 // STR<S,D,Q,W,X>pre, it can be merged.
3605 // For example:
3606 // ldr q0, [x11, #32]!
3607 // ldr q1, [x11, #16]
3608 // to
3609 // ldp q0, q1, [x11, #32]!
3610 if (MI.getOperand(1).isReg() && !IsPreLdSt) {
3611 Register BaseReg = MI.getOperand(1).getReg();
3613 if (MI.modifiesRegister(BaseReg, TRI))
3614 return false;
3615 }
3616
3617 // Pairing SVE fills/spills is only valid for little-endian targets that
3618 // implement VLS 128.
3619 switch (MI.getOpcode()) {
3620 default:
3621 break;
3622 case AArch64::LDR_ZXI:
3623 case AArch64::STR_ZXI:
3624 if (!Subtarget.isLittleEndian() ||
3625 Subtarget.getSVEVectorSizeInBits() != 128)
3626 return false;
3627 }
3628
3629 // Check if this load/store has a hint to avoid pair formation.
3630 // MachineMemOperands hints are set by the AArch64StorePairSuppress pass.
3632 return false;
3633
3634 // Do not pair any callee-save store/reload instructions in the
3635 // prologue/epilogue if the CFI information encoded the operations as separate
3636 // instructions, as that will cause the size of the actual prologue to mismatch
3637 // with the prologue size recorded in the Windows CFI.
3638 if ((MI.getFlag(MachineInstr::FrameSetup) ||
3639 MI.getFlag(MachineInstr::FrameDestroy)) &&
3640 MI.getMF()->needsWinCFI())
3641 return false;
3642
3643 // On some CPUs quad load/store pairs are slower than two single load/stores.
3644 if (Subtarget.isPaired128Slow()) {
3645 switch (MI.getOpcode()) {
3646 default:
3647 break;
3648 case AArch64::LDURQi:
3649 case AArch64::STURQi:
3650 case AArch64::LDRQui:
3651 case AArch64::STRQui:
3652 return false;
3653 }
3654 }
3655
3656 return true;
3657}
3658
3661 int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width) const {
3662 if (!LdSt.mayLoadOrStore())
3663 return false;
3664
3665 const MachineOperand *BaseOp;
3666 TypeSize WidthN(0, false);
3667 if (!getMemOperandWithOffsetWidth(LdSt, BaseOp, Offset, OffsetIsScalable,
3668 WidthN))
3669 return false;
3670 // The maximum vscale is 16 under AArch64, return the maximal extent for the
3671 // vector.
3672 Width = LocationSize::precise(WidthN);
3673 BaseOps.push_back(BaseOp);
3674 return true;
3675}
3676
3677std::optional<ExtAddrMode>
3679 const MachineOperand *Base; // Filled with the base operand of MI.
3680 int64_t Offset; // Filled with the offset of MI.
3681 bool OffsetIsScalable;
3682 if (!getMemOperandWithOffset(MemI, Base, Offset, OffsetIsScalable))
3683 return std::nullopt;
3684
3685 if (!Base->isReg())
3686 return std::nullopt;
3687 ExtAddrMode AM;
3688 AM.BaseReg = Base->getReg();
3689 AM.Displacement = Offset;
3690 AM.ScaledReg = 0;
3691 AM.Scale = 0;
3692 return AM;
3693}
3694
3696 Register Reg,
3697 const MachineInstr &AddrI,
3698 ExtAddrMode &AM) const {
3699 // Filter out instructions into which we cannot fold.
3700 unsigned NumBytes;
3701 int64_t OffsetScale = 1;
3702 switch (MemI.getOpcode()) {
3703 default:
3704 return false;
3705
3706 case AArch64::LDURQi:
3707 case AArch64::STURQi:
3708 NumBytes = 16;
3709 break;
3710
3711 case AArch64::LDURDi:
3712 case AArch64::STURDi:
3713 case AArch64::LDURXi:
3714 case AArch64::STURXi:
3715 NumBytes = 8;
3716 break;
3717
3718 case AArch64::LDURWi:
3719 case AArch64::LDURSWi:
3720 case AArch64::STURWi:
3721 NumBytes = 4;
3722 break;
3723
3724 case AArch64::LDURHi:
3725 case AArch64::STURHi:
3726 case AArch64::LDURHHi:
3727 case AArch64::STURHHi:
3728 case AArch64::LDURSHXi:
3729 case AArch64::LDURSHWi:
3730 NumBytes = 2;
3731 break;
3732
3733 case AArch64::LDRBroX:
3734 case AArch64::LDRBBroX:
3735 case AArch64::LDRSBXroX:
3736 case AArch64::LDRSBWroX:
3737 case AArch64::STRBroX:
3738 case AArch64::STRBBroX:
3739 case AArch64::LDURBi:
3740 case AArch64::LDURBBi:
3741 case AArch64::LDURSBXi:
3742 case AArch64::LDURSBWi:
3743 case AArch64::STURBi:
3744 case AArch64::STURBBi:
3745 case AArch64::LDRBui:
3746 case AArch64::LDRBBui:
3747 case AArch64::LDRSBXui:
3748 case AArch64::LDRSBWui:
3749 case AArch64::STRBui:
3750 case AArch64::STRBBui:
3751 NumBytes = 1;
3752 break;
3753
3754 case AArch64::LDRQroX:
3755 case AArch64::STRQroX:
3756 case AArch64::LDRQui:
3757 case AArch64::STRQui:
3758 NumBytes = 16;
3759 OffsetScale = 16;
3760 break;
3761
3762 case AArch64::LDRDroX:
3763 case AArch64::STRDroX:
3764 case AArch64::LDRXroX:
3765 case AArch64::STRXroX:
3766 case AArch64::LDRDui:
3767 case AArch64::STRDui:
3768 case AArch64::LDRXui:
3769 case AArch64::STRXui:
3770 NumBytes = 8;
3771 OffsetScale = 8;
3772 break;
3773
3774 case AArch64::LDRWroX:
3775 case AArch64::LDRSWroX:
3776 case AArch64::STRWroX:
3777 case AArch64::LDRWui:
3778 case AArch64::LDRSWui:
3779 case AArch64::STRWui:
3780 NumBytes = 4;
3781 OffsetScale = 4;
3782 break;
3783
3784 case AArch64::LDRHroX:
3785 case AArch64::STRHroX:
3786 case AArch64::LDRHHroX:
3787 case AArch64::STRHHroX:
3788 case AArch64::LDRSHXroX:
3789 case AArch64::LDRSHWroX:
3790 case AArch64::LDRHui:
3791 case AArch64::STRHui:
3792 case AArch64::LDRHHui:
3793 case AArch64::STRHHui:
3794 case AArch64::LDRSHXui:
3795 case AArch64::LDRSHWui:
3796 NumBytes = 2;
3797 OffsetScale = 2;
3798 break;
3799 }
3800
3801 // Check the fold operand is not the loaded/stored value.
3802 const MachineOperand &BaseRegOp = MemI.getOperand(0);
3803 if (BaseRegOp.isReg() && BaseRegOp.getReg() == Reg)
3804 return false;
3805
3806 // Handle memory instructions with a [Reg, Reg] addressing mode.
3807 if (MemI.getOperand(2).isReg()) {
3808 // Bail if the addressing mode already includes extension of the offset
3809 // register.
3810 if (MemI.getOperand(3).getImm())
3811 return false;
3812
3813 // Check if we actually have a scaled offset.
3814 if (MemI.getOperand(4).getImm() == 0)
3815 OffsetScale = 1;
3816
3817 // If the address instructions is folded into the base register, then the
3818 // addressing mode must not have a scale. Then we can swap the base and the
3819 // scaled registers.
3820 if (MemI.getOperand(1).getReg() == Reg && OffsetScale != 1)
3821 return false;
3822
3823 switch (AddrI.getOpcode()) {
3824 default:
3825 return false;
3826
3827 case AArch64::SBFMXri:
3828 // sxtw Xa, Wm
3829 // ldr Xd, [Xn, Xa, lsl #N]
3830 // ->
3831 // ldr Xd, [Xn, Wm, sxtw #N]
3832 if (AddrI.getOperand(2).getImm() != 0 ||
3833 AddrI.getOperand(3).getImm() != 31)
3834 return false;
3835
3836 AM.BaseReg = MemI.getOperand(1).getReg();
3837 if (AM.BaseReg == Reg)
3838 AM.BaseReg = MemI.getOperand(2).getReg();
3839 AM.ScaledReg = AddrI.getOperand(1).getReg();
3840 AM.Scale = OffsetScale;
3841 AM.Displacement = 0;
3843 return true;
3844
3845 case TargetOpcode::SUBREG_TO_REG: {
3846 // mov Wa, Wm
3847 // ldr Xd, [Xn, Xa, lsl #N]
3848 // ->
3849 // ldr Xd, [Xn, Wm, uxtw #N]
3850
3851 // Zero-extension looks like an ORRWrs followed by a SUBREG_TO_REG.
3852 if (AddrI.getOperand(2).getImm() != AArch64::sub_32)
3853 return false;
3854
3855 const MachineRegisterInfo &MRI = AddrI.getMF()->getRegInfo();
3856 Register OffsetReg = AddrI.getOperand(1).getReg();
3857 if (!OffsetReg.isVirtual() || !MRI.hasOneNonDBGUse(OffsetReg))
3858 return false;
3859
3860 const MachineInstr &DefMI = *MRI.getVRegDef(OffsetReg);
3861 if (DefMI.getOpcode() != AArch64::ORRWrs ||
3862 DefMI.getOperand(1).getReg() != AArch64::WZR ||
3863 DefMI.getOperand(3).getImm() != 0)
3864 return false;
3865
3866 AM.BaseReg = MemI.getOperand(1).getReg();
3867 if (AM.BaseReg == Reg)
3868 AM.BaseReg = MemI.getOperand(2).getReg();
3869 AM.ScaledReg = DefMI.getOperand(2).getReg();
3870 AM.Scale = OffsetScale;
3871 AM.Displacement = 0;
3873 return true;
3874 }
3875 }
3876 }
3877
3878 // Handle memory instructions with a [Reg, #Imm] addressing mode.
3879
3880 // Check we are not breaking a potential conversion to an LDP.
3881 auto validateOffsetForLDP = [](unsigned NumBytes, int64_t OldOffset,
3882 int64_t NewOffset) -> bool {
3883 int64_t MinOffset, MaxOffset;
3884 switch (NumBytes) {
3885 default:
3886 return true;
3887 case 4:
3888 MinOffset = -256;
3889 MaxOffset = 252;
3890 break;
3891 case 8:
3892 MinOffset = -512;
3893 MaxOffset = 504;
3894 break;
3895 case 16:
3896 MinOffset = -1024;
3897 MaxOffset = 1008;
3898 break;
3899 }
3900 return OldOffset < MinOffset || OldOffset > MaxOffset ||
3901 (NewOffset >= MinOffset && NewOffset <= MaxOffset);
3902 };
3903 auto canFoldAddSubImmIntoAddrMode = [&](int64_t Disp) -> bool {
3904 int64_t OldOffset = MemI.getOperand(2).getImm() * OffsetScale;
3905 int64_t NewOffset = OldOffset + Disp;
3906 if (!isLegalAddressingMode(NumBytes, NewOffset, /* Scale */ 0))
3907 return false;
3908 // If the old offset would fit into an LDP, but the new offset wouldn't,
3909 // bail out.
3910 if (!validateOffsetForLDP(NumBytes, OldOffset, NewOffset))
3911 return false;
3912 AM.BaseReg = AddrI.getOperand(1).getReg();
3913 AM.ScaledReg = 0;
3914 AM.Scale = 0;
3915 AM.Displacement = NewOffset;
3917 return true;
3918 };
3919
3920 auto canFoldAddRegIntoAddrMode =
3921 [&](int64_t Scale,
3923 if (MemI.getOperand(2).getImm() != 0)
3924 return false;
3925 if ((unsigned)Scale != Scale)
3926 return false;
3927 if (!isLegalAddressingMode(NumBytes, /* Offset */ 0, Scale))
3928 return false;
3929 AM.BaseReg = AddrI.getOperand(1).getReg();
3930 AM.ScaledReg = AddrI.getOperand(2).getReg();
3931 AM.Scale = Scale;
3932 AM.Displacement = 0;
3933 AM.Form = Form;
3934 return true;
3935 };
3936
3937 auto avoidSlowSTRQ = [&](const MachineInstr &MemI) {
3938 unsigned Opcode = MemI.getOpcode();
3939 return (Opcode == AArch64::STURQi || Opcode == AArch64::STRQui) &&
3940 Subtarget.isSTRQroSlow();
3941 };
3942
3943 int64_t Disp = 0;
3944 const bool OptSize = MemI.getMF()->getFunction().hasOptSize();
3945 switch (AddrI.getOpcode()) {
3946 default:
3947 return false;
3948
3949 case AArch64::ADDXri:
3950 // add Xa, Xn, #N
3951 // ldr Xd, [Xa, #M]
3952 // ->
3953 // ldr Xd, [Xn, #N'+M]
3954 Disp = AddrI.getOperand(2).getImm() << AddrI.getOperand(3).getImm();
3955 return canFoldAddSubImmIntoAddrMode(Disp);
3956
3957 case AArch64::SUBXri:
3958 // sub Xa, Xn, #N
3959 // ldr Xd, [Xa, #M]
3960 // ->
3961 // ldr Xd, [Xn, #N'+M]
3962 Disp = AddrI.getOperand(2).getImm() << AddrI.getOperand(3).getImm();
3963 return canFoldAddSubImmIntoAddrMode(-Disp);
3964
3965 case AArch64::ADDXrs: {
3966 // add Xa, Xn, Xm, lsl #N
3967 // ldr Xd, [Xa]
3968 // ->
3969 // ldr Xd, [Xn, Xm, lsl #N]
3970
3971 // Don't fold the add if the result would be slower, unless optimising for
3972 // size.
3973 unsigned Shift = static_cast<unsigned>(AddrI.getOperand(3).getImm());
3975 return false;
3976 Shift = AArch64_AM::getShiftValue(Shift);
3977 if (!OptSize) {
3978 if (Shift != 2 && Shift != 3 && Subtarget.hasAddrLSLSlow14())
3979 return false;
3980 if (avoidSlowSTRQ(MemI))
3981 return false;
3982 }
3983 return canFoldAddRegIntoAddrMode(1ULL << Shift);
3984 }
3985
3986 case AArch64::ADDXrr:
3987 // add Xa, Xn, Xm
3988 // ldr Xd, [Xa]
3989 // ->
3990 // ldr Xd, [Xn, Xm, lsl #0]
3991
3992 // Don't fold the add if the result would be slower, unless optimising for
3993 // size.
3994 if (!OptSize && avoidSlowSTRQ(MemI))
3995 return false;
3996 return canFoldAddRegIntoAddrMode(1);
3997
3998 case AArch64::ADDXrx:
3999 // add Xa, Xn, Wm, {s,u}xtw #N
4000 // ldr Xd, [Xa]
4001 // ->
4002 // ldr Xd, [Xn, Wm, {s,u}xtw #N]
4003
4004 // Don't fold the add if the result would be slower, unless optimising for
4005 // size.
4006 if (!OptSize && avoidSlowSTRQ(MemI))
4007 return false;
4008
4009 // Can fold only sign-/zero-extend of a word.
4010 unsigned Imm = static_cast<unsigned>(AddrI.getOperand(3).getImm());
4012 if (Extend != AArch64_AM::UXTW && Extend != AArch64_AM::SXTW)
4013 return false;
4014
4015 return canFoldAddRegIntoAddrMode(
4019 }
4020}
4021
4022// Given an opcode for an instruction with a [Reg, #Imm] addressing mode,
4023// return the opcode of an instruction performing the same operation, but using
4024// the [Reg, Reg] addressing mode.
4025static unsigned regOffsetOpcode(unsigned Opcode) {
4026 switch (Opcode) {
4027 default:
4028 llvm_unreachable("Address folding not implemented for instruction");
4029
4030 case AArch64::LDURQi:
4031 case AArch64::LDRQui:
4032 return AArch64::LDRQroX;
4033 case AArch64::STURQi:
4034 case AArch64::STRQui:
4035 return AArch64::STRQroX;
4036 case AArch64::LDURDi:
4037 case AArch64::LDRDui:
4038 return AArch64::LDRDroX;
4039 case AArch64::STURDi:
4040 case AArch64::STRDui:
4041 return AArch64::STRDroX;
4042 case AArch64::LDURXi:
4043 case AArch64::LDRXui:
4044 return AArch64::LDRXroX;
4045 case AArch64::STURXi:
4046 case AArch64::STRXui:
4047 return AArch64::STRXroX;
4048 case AArch64::LDURWi:
4049 case AArch64::LDRWui:
4050 return AArch64::LDRWroX;
4051 case AArch64::LDURSWi:
4052 case AArch64::LDRSWui:
4053 return AArch64::LDRSWroX;
4054 case AArch64::STURWi:
4055 case AArch64::STRWui:
4056 return AArch64::STRWroX;
4057 case AArch64::LDURHi:
4058 case AArch64::LDRHui:
4059 return AArch64::LDRHroX;
4060 case AArch64::STURHi:
4061 case AArch64::STRHui:
4062 return AArch64::STRHroX;
4063 case AArch64::LDURHHi:
4064 case AArch64::LDRHHui:
4065 return AArch64::LDRHHroX;
4066 case AArch64::STURHHi:
4067 case AArch64::STRHHui:
4068 return AArch64::STRHHroX;
4069 case AArch64::LDURSHXi:
4070 case AArch64::LDRSHXui:
4071 return AArch64::LDRSHXroX;
4072 case AArch64::LDURSHWi:
4073 case AArch64::LDRSHWui:
4074 return AArch64::LDRSHWroX;
4075 case AArch64::LDURBi:
4076 case AArch64::LDRBui:
4077 return AArch64::LDRBroX;
4078 case AArch64::LDURBBi:
4079 case AArch64::LDRBBui:
4080 return AArch64::LDRBBroX;
4081 case AArch64::LDURSBXi:
4082 case AArch64::LDRSBXui:
4083 return AArch64::LDRSBXroX;
4084 case AArch64::LDURSBWi:
4085 case AArch64::LDRSBWui:
4086 return AArch64::LDRSBWroX;
4087 case AArch64::STURBi:
4088 case AArch64::STRBui:
4089 return AArch64::STRBroX;
4090 case AArch64::STURBBi:
4091 case AArch64::STRBBui:
4092 return AArch64::STRBBroX;
4093 }
4094}
4095
4096// Given an opcode for an instruction with a [Reg, #Imm] addressing mode, return
4097// the opcode of an instruction performing the same operation, but using the
4098// [Reg, #Imm] addressing mode with scaled offset.
4099unsigned scaledOffsetOpcode(unsigned Opcode, unsigned &Scale) {
4100 switch (Opcode) {
4101 default:
4102 llvm_unreachable("Address folding not implemented for instruction");
4103
4104 case AArch64::LDURQi:
4105 Scale = 16;
4106 return AArch64::LDRQui;
4107 case AArch64::STURQi:
4108 Scale = 16;
4109 return AArch64::STRQui;
4110 case AArch64::LDURDi:
4111 Scale = 8;
4112 return AArch64::LDRDui;
4113 case AArch64::STURDi:
4114 Scale = 8;
4115 return AArch64::STRDui;
4116 case AArch64::LDURXi:
4117 Scale = 8;
4118 return AArch64::LDRXui;
4119 case AArch64::STURXi:
4120 Scale = 8;
4121 return AArch64::STRXui;
4122 case AArch64::LDURWi:
4123 Scale = 4;
4124 return AArch64::LDRWui;
4125 case AArch64::LDURSWi:
4126 Scale = 4;
4127 return AArch64::LDRSWui;
4128 case AArch64::STURWi:
4129 Scale = 4;
4130 return AArch64::STRWui;
4131 case AArch64::LDURHi:
4132 Scale = 2;
4133 return AArch64::LDRHui;
4134 case AArch64::STURHi:
4135 Scale = 2;
4136 return AArch64::STRHui;
4137 case AArch64::LDURHHi:
4138 Scale = 2;
4139 return AArch64::LDRHHui;
4140 case AArch64::STURHHi:
4141 Scale = 2;
4142 return AArch64::STRHHui;
4143 case AArch64::LDURSHXi:
4144 Scale = 2;
4145 return AArch64::LDRSHXui;
4146 case AArch64::LDURSHWi:
4147 Scale = 2;
4148 return AArch64::LDRSHWui;
4149 case AArch64::LDURBi:
4150 Scale = 1;
4151 return AArch64::LDRBui;
4152 case AArch64::LDURBBi:
4153 Scale = 1;
4154 return AArch64::LDRBBui;
4155 case AArch64::LDURSBXi:
4156 Scale = 1;
4157 return AArch64::LDRSBXui;
4158 case AArch64::LDURSBWi:
4159 Scale = 1;
4160 return AArch64::LDRSBWui;
4161 case AArch64::STURBi:
4162 Scale = 1;
4163 return AArch64::STRBui;
4164 case AArch64::STURBBi:
4165 Scale = 1;
4166 return AArch64::STRBBui;
4167 case AArch64::LDRQui:
4168 case AArch64::STRQui:
4169 Scale = 16;
4170 return Opcode;
4171 case AArch64::LDRDui:
4172 case AArch64::STRDui:
4173 case AArch64::LDRXui:
4174 case AArch64::STRXui:
4175 Scale = 8;
4176 return Opcode;
4177 case AArch64::LDRWui:
4178 case AArch64::LDRSWui:
4179 case AArch64::STRWui:
4180 Scale = 4;
4181 return Opcode;
4182 case AArch64::LDRHui:
4183 case AArch64::STRHui:
4184 case AArch64::LDRHHui:
4185 case AArch64::STRHHui:
4186 case AArch64::LDRSHXui:
4187 case AArch64::LDRSHWui:
4188 Scale = 2;
4189 return Opcode;
4190 case AArch64::LDRBui:
4191 case AArch64::LDRBBui:
4192 case AArch64::LDRSBXui:
4193 case AArch64::LDRSBWui:
4194 case AArch64::STRBui:
4195 case AArch64::STRBBui:
4196 Scale = 1;
4197 return Opcode;
4198 }
4199}
4200
4201// Given an opcode for an instruction with a [Reg, #Imm] addressing mode, return
4202// the opcode of an instruction performing the same operation, but using the
4203// [Reg, #Imm] addressing mode with unscaled offset.
4204unsigned unscaledOffsetOpcode(unsigned Opcode) {
4205 switch (Opcode) {
4206 default:
4207 llvm_unreachable("Address folding not implemented for instruction");
4208
4209 case AArch64::LDURQi:
4210 case AArch64::STURQi:
4211 case AArch64::LDURDi:
4212 case AArch64::STURDi:
4213 case AArch64::LDURXi:
4214 case AArch64::STURXi:
4215 case AArch64::LDURWi:
4216 case AArch64::LDURSWi:
4217 case AArch64::STURWi:
4218 case AArch64::LDURHi:
4219 case AArch64::STURHi:
4220 case AArch64::LDURHHi:
4221 case AArch64::STURHHi:
4222 case AArch64::LDURSHXi:
4223 case AArch64::LDURSHWi:
4224 case AArch64::LDURBi:
4225 case AArch64::STURBi:
4226 case AArch64::LDURBBi:
4227 case AArch64::STURBBi:
4228 case AArch64::LDURSBWi:
4229 case AArch64::LDURSBXi:
4230 return Opcode;
4231 case AArch64::LDRQui:
4232 return AArch64::LDURQi;
4233 case AArch64::STRQui:
4234 return AArch64::STURQi;
4235 case AArch64::LDRDui:
4236 return AArch64::LDURDi;
4237 case AArch64::STRDui:
4238 return AArch64::STURDi;
4239 case AArch64::LDRXui:
4240 return AArch64::LDURXi;
4241 case AArch64::STRXui:
4242 return AArch64::STURXi;
4243 case AArch64::LDRWui:
4244 return AArch64::LDURWi;
4245 case AArch64::LDRSWui:
4246 return AArch64::LDURSWi;
4247 case AArch64::STRWui:
4248 return AArch64::STURWi;
4249 case AArch64::LDRHui:
4250 return AArch64::LDURHi;
4251 case AArch64::STRHui:
4252 return AArch64::STURHi;
4253 case AArch64::LDRHHui:
4254 return AArch64::LDURHHi;
4255 case AArch64::STRHHui:
4256 return AArch64::STURHHi;
4257 case AArch64::LDRSHXui:
4258 return AArch64::LDURSHXi;
4259 case AArch64::LDRSHWui:
4260 return AArch64::LDURSHWi;
4261 case AArch64::LDRBBui:
4262 return AArch64::LDURBBi;
4263 case AArch64::LDRBui:
4264 return AArch64::LDURBi;
4265 case AArch64::STRBBui:
4266 return AArch64::STURBBi;
4267 case AArch64::STRBui:
4268 return AArch64::STURBi;
4269 case AArch64::LDRSBWui:
4270 return AArch64::LDURSBWi;
4271 case AArch64::LDRSBXui:
4272 return AArch64::LDURSBXi;
4273 }
4274}
4275
4276// Given the opcode of a memory load/store instruction, return the opcode of an
4277// instruction performing the same operation, but using
4278// the [Reg, Reg, {s,u}xtw #N] addressing mode with sign-/zero-extend of the
4279// offset register.
4280static unsigned offsetExtendOpcode(unsigned Opcode) {
4281 switch (Opcode) {
4282 default:
4283 llvm_unreachable("Address folding not implemented for instruction");
4284
4285 case AArch64::LDRQroX:
4286 case AArch64::LDURQi:
4287 case AArch64::LDRQui:
4288 return AArch64::LDRQroW;
4289 case AArch64::STRQroX:
4290 case AArch64::STURQi:
4291 case AArch64::STRQui:
4292 return AArch64::STRQroW;
4293 case AArch64::LDRDroX:
4294 case AArch64::LDURDi:
4295 case AArch64::LDRDui:
4296 return AArch64::LDRDroW;
4297 case AArch64::STRDroX:
4298 case AArch64::STURDi:
4299 case AArch64::STRDui:
4300 return AArch64::STRDroW;
4301 case AArch64::LDRXroX:
4302 case AArch64::LDURXi:
4303 case AArch64::LDRXui:
4304 return AArch64::LDRXroW;
4305 case AArch64::STRXroX:
4306 case AArch64::STURXi:
4307 case AArch64::STRXui:
4308 return AArch64::STRXroW;
4309 case AArch64::LDRWroX:
4310 case AArch64::LDURWi:
4311 case AArch64::LDRWui:
4312 return AArch64::LDRWroW;
4313 case AArch64::LDRSWroX:
4314 case AArch64::LDURSWi:
4315 case AArch64::LDRSWui:
4316 return AArch64::LDRSWroW;
4317 case AArch64::STRWroX:
4318 case AArch64::STURWi:
4319 case AArch64::STRWui:
4320 return AArch64::STRWroW;
4321 case AArch64::LDRHroX:
4322 case AArch64::LDURHi:
4323 case AArch64::LDRHui:
4324 return AArch64::LDRHroW;
4325 case AArch64::STRHroX:
4326 case AArch64::STURHi:
4327 case AArch64::STRHui:
4328 return AArch64::STRHroW;
4329 case AArch64::LDRHHroX:
4330 case AArch64::LDURHHi:
4331 case AArch64::LDRHHui:
4332 return AArch64::LDRHHroW;
4333 case AArch64::STRHHroX:
4334 case AArch64::STURHHi:
4335 case AArch64::STRHHui:
4336 return AArch64::STRHHroW;
4337 case AArch64::LDRSHXroX:
4338 case AArch64::LDURSHXi:
4339 case AArch64::LDRSHXui:
4340 return AArch64::LDRSHXroW;
4341 case AArch64::LDRSHWroX:
4342 case AArch64::LDURSHWi:
4343 case AArch64::LDRSHWui:
4344 return AArch64::LDRSHWroW;
4345 case AArch64::LDRBroX:
4346 case AArch64::LDURBi:
4347 case AArch64::LDRBui:
4348 return AArch64::LDRBroW;
4349 case AArch64::LDRBBroX:
4350 case AArch64::LDURBBi:
4351 case AArch64::LDRBBui:
4352 return AArch64::LDRBBroW;
4353 case AArch64::LDRSBXroX:
4354 case AArch64::LDURSBXi:
4355 case AArch64::LDRSBXui:
4356 return AArch64::LDRSBXroW;
4357 case AArch64::LDRSBWroX:
4358 case AArch64::LDURSBWi:
4359 case AArch64::LDRSBWui:
4360 return AArch64::LDRSBWroW;
4361 case AArch64::STRBroX:
4362 case AArch64::STURBi:
4363 case AArch64::STRBui:
4364 return AArch64::STRBroW;
4365 case AArch64::STRBBroX:
4366 case AArch64::STURBBi:
4367 case AArch64::STRBBui:
4368 return AArch64::STRBBroW;
4369 }
4370}
4371
4373 const ExtAddrMode &AM) const {
4374
4375 const DebugLoc &DL = MemI.getDebugLoc();
4376 MachineBasicBlock &MBB = *MemI.getParent();
4378
4380 if (AM.ScaledReg) {
4381 // The new instruction will be in the form `ldr Rt, [Xn, Xm, lsl #imm]`.
4382 unsigned Opcode = regOffsetOpcode(MemI.getOpcode());
4383 MRI.constrainRegClass(AM.BaseReg, &AArch64::GPR64spRegClass);
4384 auto B = BuildMI(MBB, MemI, DL, get(Opcode))
4385 .addReg(MemI.getOperand(0).getReg(),
4386 getDefRegState(MemI.mayLoad()))
4387 .addReg(AM.BaseReg)
4388 .addReg(AM.ScaledReg)
4389 .addImm(0)
4390 .addImm(AM.Scale > 1)
4391 .setMemRefs(MemI.memoperands())
4392 .setMIFlags(MemI.getFlags());
4393 return B.getInstr();
4394 }
4395
4396 assert(AM.ScaledReg == 0 && AM.Scale == 0 &&
4397 "Addressing mode not supported for folding");
4398
4399 // The new instruction will be in the form `ld[u]r Rt, [Xn, #imm]`.
4400 unsigned Scale = 1;
4401 unsigned Opcode = MemI.getOpcode();
4402 if (isInt<9>(AM.Displacement))
4403 Opcode = unscaledOffsetOpcode(Opcode);
4404 else
4405 Opcode = scaledOffsetOpcode(Opcode, Scale);
4406
4407 auto B =
4408 BuildMI(MBB, MemI, DL, get(Opcode))
4409 .addReg(MemI.getOperand(0).getReg(), getDefRegState(MemI.mayLoad()))
4410 .addReg(AM.BaseReg)
4411 .addImm(AM.Displacement / Scale)
4412 .setMemRefs(MemI.memoperands())
4413 .setMIFlags(MemI.getFlags());
4414 return B.getInstr();
4415 }
4416
4419 // The new instruction will be in the form `ldr Rt, [Xn, Wm, {s,u}xtw #N]`.
4420 assert(AM.ScaledReg && !AM.Displacement &&
4421 "Address offset can be a register or an immediate, but not both");
4422 unsigned Opcode = offsetExtendOpcode(MemI.getOpcode());
4423 MRI.constrainRegClass(AM.BaseReg, &AArch64::GPR64spRegClass);
4424 // Make sure the offset register is in the correct register class.
4425 Register OffsetReg = AM.ScaledReg;
4426 const TargetRegisterClass *RC = MRI.getRegClass(OffsetReg);
4427 if (RC->hasSuperClassEq(&AArch64::GPR64RegClass)) {
4428 OffsetReg = MRI.createVirtualRegister(&AArch64::GPR32RegClass);
4429 BuildMI(MBB, MemI, DL, get(TargetOpcode::COPY), OffsetReg)
4430 .addReg(AM.ScaledReg, {}, AArch64::sub_32);
4431 }
4432 auto B =
4433 BuildMI(MBB, MemI, DL, get(Opcode))
4434 .addReg(MemI.getOperand(0).getReg(), getDefRegState(MemI.mayLoad()))
4435 .addReg(AM.BaseReg)
4436 .addReg(OffsetReg)
4438 .addImm(AM.Scale != 1)
4439 .setMemRefs(MemI.memoperands())
4440 .setMIFlags(MemI.getFlags());
4441
4442 return B.getInstr();
4443 }
4444
4446 "Function must not be called with an addressing mode it can't handle");
4447}
4448
4449/// Return true if the opcode is a post-index ld/st instruction, which really
4450/// loads from base+0.
4451static bool isPostIndexLdStOpcode(unsigned Opcode) {
4452 switch (Opcode) {
4453 default:
4454 return false;
4455 case AArch64::LD1Fourv16b_POST:
4456 case AArch64::LD1Fourv1d_POST:
4457 case AArch64::LD1Fourv2d_POST:
4458 case AArch64::LD1Fourv2s_POST:
4459 case AArch64::LD1Fourv4h_POST:
4460 case AArch64::LD1Fourv4s_POST:
4461 case AArch64::LD1Fourv8b_POST:
4462 case AArch64::LD1Fourv8h_POST:
4463 case AArch64::LD1Onev16b_POST:
4464 case AArch64::LD1Onev1d_POST:
4465 case AArch64::LD1Onev2d_POST:
4466 case AArch64::LD1Onev2s_POST:
4467 case AArch64::LD1Onev4h_POST:
4468 case AArch64::LD1Onev4s_POST:
4469 case AArch64::LD1Onev8b_POST:
4470 case AArch64::LD1Onev8h_POST:
4471 case AArch64::LD1Rv16b_POST:
4472 case AArch64::LD1Rv1d_POST:
4473 case AArch64::LD1Rv2d_POST:
4474 case AArch64::LD1Rv2s_POST:
4475 case AArch64::LD1Rv4h_POST:
4476 case AArch64::LD1Rv4s_POST:
4477 case AArch64::LD1Rv8b_POST:
4478 case AArch64::LD1Rv8h_POST:
4479 case AArch64::LD1Threev16b_POST:
4480 case AArch64::LD1Threev1d_POST:
4481 case AArch64::LD1Threev2d_POST:
4482 case AArch64::LD1Threev2s_POST:
4483 case AArch64::LD1Threev4h_POST:
4484 case AArch64::LD1Threev4s_POST:
4485 case AArch64::LD1Threev8b_POST:
4486 case AArch64::LD1Threev8h_POST:
4487 case AArch64::LD1Twov16b_POST:
4488 case AArch64::LD1Twov1d_POST:
4489 case AArch64::LD1Twov2d_POST:
4490 case AArch64::LD1Twov2s_POST:
4491 case AArch64::LD1Twov4h_POST:
4492 case AArch64::LD1Twov4s_POST:
4493 case AArch64::LD1Twov8b_POST:
4494 case AArch64::LD1Twov8h_POST:
4495 case AArch64::LD1i16_POST:
4496 case AArch64::LD1i32_POST:
4497 case AArch64::LD1i64_POST:
4498 case AArch64::LD1i8_POST:
4499 case AArch64::LD2Rv16b_POST:
4500 case AArch64::LD2Rv1d_POST:
4501 case AArch64::LD2Rv2d_POST:
4502 case AArch64::LD2Rv2s_POST:
4503 case AArch64::LD2Rv4h_POST:
4504 case AArch64::LD2Rv4s_POST:
4505 case AArch64::LD2Rv8b_POST:
4506 case AArch64::LD2Rv8h_POST:
4507 case AArch64::LD2Twov16b_POST:
4508 case AArch64::LD2Twov2d_POST:
4509 case AArch64::LD2Twov2s_POST:
4510 case AArch64::LD2Twov4h_POST:
4511 case AArch64::LD2Twov4s_POST:
4512 case AArch64::LD2Twov8b_POST:
4513 case AArch64::LD2Twov8h_POST:
4514 case AArch64::LD2i16_POST:
4515 case AArch64::LD2i32_POST:
4516 case AArch64::LD2i64_POST:
4517 case AArch64::LD2i8_POST:
4518 case AArch64::LD3Rv16b_POST:
4519 case AArch64::LD3Rv1d_POST:
4520 case AArch64::LD3Rv2d_POST:
4521 case AArch64::LD3Rv2s_POST:
4522 case AArch64::LD3Rv4h_POST:
4523 case AArch64::LD3Rv4s_POST:
4524 case AArch64::LD3Rv8b_POST:
4525 case AArch64::LD3Rv8h_POST:
4526 case AArch64::LD3Threev16b_POST:
4527 case AArch64::LD3Threev2d_POST:
4528 case AArch64::LD3Threev2s_POST:
4529 case AArch64::LD3Threev4h_POST:
4530 case AArch64::LD3Threev4s_POST:
4531 case AArch64::LD3Threev8b_POST:
4532 case AArch64::LD3Threev8h_POST:
4533 case AArch64::LD3i16_POST:
4534 case AArch64::LD3i32_POST:
4535 case AArch64::LD3i64_POST:
4536 case AArch64::LD3i8_POST:
4537 case AArch64::LD4Fourv16b_POST:
4538 case AArch64::LD4Fourv2d_POST:
4539 case AArch64::LD4Fourv2s_POST:
4540 case AArch64::LD4Fourv4h_POST:
4541 case AArch64::LD4Fourv4s_POST:
4542 case AArch64::LD4Fourv8b_POST:
4543 case AArch64::LD4Fourv8h_POST:
4544 case AArch64::LD4Rv16b_POST:
4545 case AArch64::LD4Rv1d_POST:
4546 case AArch64::LD4Rv2d_POST:
4547 case AArch64::LD4Rv2s_POST:
4548 case AArch64::LD4Rv4h_POST:
4549 case AArch64::LD4Rv4s_POST:
4550 case AArch64::LD4Rv8b_POST:
4551 case AArch64::LD4Rv8h_POST:
4552 case AArch64::LD4i16_POST:
4553 case AArch64::LD4i32_POST:
4554 case AArch64::LD4i64_POST:
4555 case AArch64::LD4i8_POST:
4556 case AArch64::LDAPRWpost:
4557 case AArch64::LDAPRXpost:
4558 case AArch64::LDIAPPWpost:
4559 case AArch64::LDIAPPXpost:
4560 case AArch64::LDPDpost:
4561 case AArch64::LDPQpost:
4562 case AArch64::LDPSWpost:
4563 case AArch64::LDPSpost:
4564 case AArch64::LDPWpost:
4565 case AArch64::LDPXpost:
4566 case AArch64::LDRBBpost:
4567 case AArch64::LDRBpost:
4568 case AArch64::LDRDpost:
4569 case AArch64::LDRHHpost:
4570 case AArch64::LDRHpost:
4571 case AArch64::LDRQpost:
4572 case AArch64::LDRSBWpost:
4573 case AArch64::LDRSBXpost:
4574 case AArch64::LDRSHWpost:
4575 case AArch64::LDRSHXpost:
4576 case AArch64::LDRSWpost:
4577 case AArch64::LDRSpost:
4578 case AArch64::LDRWpost:
4579 case AArch64::LDRXpost:
4580 case AArch64::ST1Fourv16b_POST:
4581 case AArch64::ST1Fourv1d_POST:
4582 case AArch64::ST1Fourv2d_POST:
4583 case AArch64::ST1Fourv2s_POST:
4584 case AArch64::ST1Fourv4h_POST:
4585 case AArch64::ST1Fourv4s_POST:
4586 case AArch64::ST1Fourv8b_POST:
4587 case AArch64::ST1Fourv8h_POST:
4588 case AArch64::ST1Onev16b_POST:
4589 case AArch64::ST1Onev1d_POST:
4590 case AArch64::ST1Onev2d_POST:
4591 case AArch64::ST1Onev2s_POST:
4592 case AArch64::ST1Onev4h_POST:
4593 case AArch64::ST1Onev4s_POST:
4594 case AArch64::ST1Onev8b_POST:
4595 case AArch64::ST1Onev8h_POST:
4596 case AArch64::ST1Threev16b_POST:
4597 case AArch64::ST1Threev1d_POST:
4598 case AArch64::ST1Threev2d_POST:
4599 case AArch64::ST1Threev2s_POST:
4600 case AArch64::ST1Threev4h_POST:
4601 case AArch64::ST1Threev4s_POST:
4602 case AArch64::ST1Threev8b_POST:
4603 case AArch64::ST1Threev8h_POST:
4604 case AArch64::ST1Twov16b_POST:
4605 case AArch64::ST1Twov1d_POST:
4606 case AArch64::ST1Twov2d_POST:
4607 case AArch64::ST1Twov2s_POST:
4608 case AArch64::ST1Twov4h_POST:
4609 case AArch64::ST1Twov4s_POST:
4610 case AArch64::ST1Twov8b_POST:
4611 case AArch64::ST1Twov8h_POST:
4612 case AArch64::ST1i16_POST:
4613 case AArch64::ST1i32_POST:
4614 case AArch64::ST1i64_POST:
4615 case AArch64::ST1i8_POST:
4616 case AArch64::ST2GPostIndex:
4617 case AArch64::ST2Twov16b_POST:
4618 case AArch64::ST2Twov2d_POST:
4619 case AArch64::ST2Twov2s_POST:
4620 case AArch64::ST2Twov4h_POST:
4621 case AArch64::ST2Twov4s_POST:
4622 case AArch64::ST2Twov8b_POST:
4623 case AArch64::ST2Twov8h_POST:
4624 case AArch64::ST2i16_POST:
4625 case AArch64::ST2i32_POST:
4626 case AArch64::ST2i64_POST:
4627 case AArch64::ST2i8_POST:
4628 case AArch64::ST3Threev16b_POST:
4629 case AArch64::ST3Threev2d_POST:
4630 case AArch64::ST3Threev2s_POST:
4631 case AArch64::ST3Threev4h_POST:
4632 case AArch64::ST3Threev4s_POST:
4633 case AArch64::ST3Threev8b_POST:
4634 case AArch64::ST3Threev8h_POST:
4635 case AArch64::ST3i16_POST:
4636 case AArch64::ST3i32_POST:
4637 case AArch64::ST3i64_POST:
4638 case AArch64::ST3i8_POST:
4639 case AArch64::ST4Fourv16b_POST:
4640 case AArch64::ST4Fourv2d_POST:
4641 case AArch64::ST4Fourv2s_POST:
4642 case AArch64::ST4Fourv4h_POST:
4643 case AArch64::ST4Fourv4s_POST:
4644 case AArch64::ST4Fourv8b_POST:
4645 case AArch64::ST4Fourv8h_POST:
4646 case AArch64::ST4i16_POST:
4647 case AArch64::ST4i32_POST:
4648 case AArch64::ST4i64_POST:
4649 case AArch64::ST4i8_POST:
4650 case AArch64::STGPostIndex:
4651 case AArch64::STGPpost:
4652 case AArch64::STPDpost:
4653 case AArch64::STPQpost:
4654 case AArch64::STPSpost:
4655 case AArch64::STPWpost:
4656 case AArch64::STPXpost:
4657 case AArch64::STRBBpost:
4658 case AArch64::STRBpost:
4659 case AArch64::STRDpost:
4660 case AArch64::STRHHpost:
4661 case AArch64::STRHpost:
4662 case AArch64::STRQpost:
4663 case AArch64::STRSpost:
4664 case AArch64::STRWpost:
4665 case AArch64::STRXpost:
4666 case AArch64::STZ2GPostIndex:
4667 case AArch64::STZGPostIndex:
4668 return true;
4669 }
4670}
4671
4673 const MachineInstr &LdSt, const MachineOperand *&BaseOp, int64_t &Offset,
4674 bool &OffsetIsScalable, TypeSize &Width) const {
4675 assert(LdSt.mayLoadOrStore() && "Expected a memory operation.");
4676 // Handle only loads/stores with base register followed by immediate offset.
4677 if (LdSt.getNumExplicitOperands() == 3) {
4678 // Non-paired instruction (e.g., ldr x1, [x0, #8]).
4679 if ((!LdSt.getOperand(1).isReg() && !LdSt.getOperand(1).isFI()) ||
4680 !LdSt.getOperand(2).isImm())
4681 return false;
4682 } else if (LdSt.getNumExplicitOperands() == 4) {
4683 // Paired instruction (e.g., ldp x1, x2, [x0, #8]).
4684 if (!LdSt.getOperand(1).isReg() ||
4685 (!LdSt.getOperand(2).isReg() && !LdSt.getOperand(2).isFI()) ||
4686 !LdSt.getOperand(3).isImm())
4687 return false;
4688 } else
4689 return false;
4690
4691 // Get the scaling factor for the instruction and set the width for the
4692 // instruction.
4693 TypeSize Scale(0U, false);
4694 int64_t Dummy1, Dummy2;
4695
4696 // If this returns false, then it's an instruction we don't want to handle.
4697 if (!getMemOpInfo(LdSt.getOpcode(), Scale, Width, Dummy1, Dummy2))
4698 return false;
4699
4700 // Compute the offset. Offset is calculated as the immediate operand
4701 // multiplied by the scaling factor. Unscaled instructions have scaling factor
4702 // set to 1. Postindex are a special case which have an offset of 0.
4703 if (isPostIndexLdStOpcode(LdSt.getOpcode())) {
4704 BaseOp = &LdSt.getOperand(2);
4705 Offset = 0;
4706 } else if (LdSt.getNumExplicitOperands() == 3) {
4707 BaseOp = &LdSt.getOperand(1);
4708 Offset = LdSt.getOperand(2).getImm() * Scale.getKnownMinValue();
4709 } else {
4710 assert(LdSt.getNumExplicitOperands() == 4 && "invalid number of operands");
4711 BaseOp = &LdSt.getOperand(2);
4712 Offset = LdSt.getOperand(3).getImm() * Scale.getKnownMinValue();
4713 }
4714 OffsetIsScalable = Scale.isScalable();
4715
4716 return BaseOp->isReg() || BaseOp->isFI();
4717}
4718
4721 assert(LdSt.mayLoadOrStore() && "Expected a memory operation.");
4722 MachineOperand &OfsOp = LdSt.getOperand(LdSt.getNumExplicitOperands() - 1);
4723 assert(OfsOp.isImm() && "Offset operand wasn't immediate.");
4724 return OfsOp;
4725}
4726
4727bool AArch64InstrInfo::getMemOpInfo(unsigned Opcode, TypeSize &Scale,
4728 TypeSize &Width, int64_t &MinOffset,
4729 int64_t &MaxOffset) {
4730 switch (Opcode) {
4731 // Not a memory operation or something we want to handle.
4732 default:
4733 Scale = Width = TypeSize::getFixed(0);
4734 MinOffset = MaxOffset = 0;
4735 return false;
4736 // LDR / STR
4737 case AArch64::LDRQui:
4738 case AArch64::STRQui:
4739 Scale = Width = TypeSize::getFixed(16);
4740 MinOffset = 0;
4741 MaxOffset = 4095;
4742 break;
4743 case AArch64::LDRXui:
4744 case AArch64::LDRDui:
4745 case AArch64::STRXui:
4746 case AArch64::STRDui:
4747 case AArch64::PRFMui:
4748 case AArch64::ATOMIC_STORE_HINT_Xui:
4749 case AArch64::ATOMIC_STORE_HINT_Dui:
4750 Scale = Width = TypeSize::getFixed(8);
4751 MinOffset = 0;
4752 MaxOffset = 4095;
4753 break;
4754 case AArch64::LDRWui:
4755 case AArch64::LDRSui:
4756 case AArch64::LDRSWui:
4757 case AArch64::STRWui:
4758 case AArch64::STRSui:
4759 case AArch64::ATOMIC_STORE_HINT_Wui:
4760 case AArch64::ATOMIC_STORE_HINT_Sui:
4761 Scale = Width = TypeSize::getFixed(4);
4762 MinOffset = 0;
4763 MaxOffset = 4095;
4764 break;
4765 case AArch64::LDRHui:
4766 case AArch64::LDRHHui:
4767 case AArch64::LDRSHWui:
4768 case AArch64::LDRSHXui:
4769 case AArch64::STRHui:
4770 case AArch64::STRHHui:
4771 case AArch64::ATOMIC_STORE_HINT_Hui:
4772 Scale = Width = TypeSize::getFixed(2);
4773 MinOffset = 0;
4774 MaxOffset = 4095;
4775 break;
4776 case AArch64::LDRBui:
4777 case AArch64::LDRBBui:
4778 case AArch64::LDRSBWui:
4779 case AArch64::LDRSBXui:
4780 case AArch64::STRBui:
4781 case AArch64::STRBBui:
4782 case AArch64::ATOMIC_STORE_HINT_Bui:
4783 Scale = Width = TypeSize::getFixed(1);
4784 MinOffset = 0;
4785 MaxOffset = 4095;
4786 break;
4787 // post/pre inc
4788 case AArch64::STRQpre:
4789 case AArch64::LDRQpost:
4790 Scale = TypeSize::getFixed(1);
4791 Width = TypeSize::getFixed(16);
4792 MinOffset = -256;
4793 MaxOffset = 255;
4794 break;
4795 case AArch64::LDRDpost:
4796 case AArch64::LDRDpre:
4797 case AArch64::LDRXpost:
4798 case AArch64::LDRXpre:
4799 case AArch64::STRDpost:
4800 case AArch64::STRDpre:
4801 case AArch64::STRXpost:
4802 case AArch64::STRXpre:
4803 Scale = TypeSize::getFixed(1);
4804 Width = TypeSize::getFixed(8);
4805 MinOffset = -256;
4806 MaxOffset = 255;
4807 break;
4808 case AArch64::STRWpost:
4809 case AArch64::STRWpre:
4810 case AArch64::LDRWpost:
4811 case AArch64::LDRWpre:
4812 case AArch64::STRSpost:
4813 case AArch64::STRSpre:
4814 case AArch64::LDRSpost:
4815 case AArch64::LDRSpre:
4816 Scale = TypeSize::getFixed(1);
4817 Width = TypeSize::getFixed(4);
4818 MinOffset = -256;
4819 MaxOffset = 255;
4820 break;
4821 case AArch64::LDRHpost:
4822 case AArch64::LDRHpre:
4823 case AArch64::STRHpost:
4824 case AArch64::STRHpre:
4825 case AArch64::LDRHHpost:
4826 case AArch64::LDRHHpre:
4827 case AArch64::STRHHpost:
4828 case AArch64::STRHHpre:
4829 Scale = TypeSize::getFixed(1);
4830 Width = TypeSize::getFixed(2);
4831 MinOffset = -256;
4832 MaxOffset = 255;
4833 break;
4834 case AArch64::LDRBpost:
4835 case AArch64::LDRBpre:
4836 case AArch64::STRBpost:
4837 case AArch64::STRBpre:
4838 case AArch64::LDRBBpost:
4839 case AArch64::LDRBBpre:
4840 case AArch64::STRBBpost:
4841 case AArch64::STRBBpre:
4842 Scale = Width = TypeSize::getFixed(1);
4843 MinOffset = -256;
4844 MaxOffset = 255;
4845 break;
4846 // Unscaled
4847 case AArch64::LDURQi:
4848 case AArch64::STURQi:
4849 Scale = TypeSize::getFixed(1);
4850 Width = TypeSize::getFixed(16);
4851 MinOffset = -256;
4852 MaxOffset = 255;
4853 break;
4854 case AArch64::LDURXi:
4855 case AArch64::LDURDi:
4856 case AArch64::LDAPURXi:
4857 case AArch64::STURXi:
4858 case AArch64::STURDi:
4859 case AArch64::STLURXi:
4860 case AArch64::PRFUMi:
4861 case AArch64::ATOMIC_STORE_HINT_Xi:
4862 case AArch64::ATOMIC_STORE_HINT_Di:
4863 Scale = TypeSize::getFixed(1);
4864 Width = TypeSize::getFixed(8);
4865 MinOffset = -256;
4866 MaxOffset = 255;
4867 break;
4868 case AArch64::LDURWi:
4869 case AArch64::LDURSi:
4870 case AArch64::LDURSWi:
4871 case AArch64::LDAPURi:
4872 case AArch64::LDAPURSWi:
4873 case AArch64::STURWi:
4874 case AArch64::STURSi:
4875 case AArch64::STLURWi:
4876 case AArch64::ATOMIC_STORE_HINT_Wi:
4877 case AArch64::ATOMIC_STORE_HINT_Si:
4878 Scale = TypeSize::getFixed(1);
4879 Width = TypeSize::getFixed(4);
4880 MinOffset = -256;
4881 MaxOffset = 255;
4882 break;
4883 case AArch64::LDURHi:
4884 case AArch64::LDURHHi:
4885 case AArch64::LDURSHXi:
4886 case AArch64::LDURSHWi:
4887 case AArch64::LDAPURHi:
4888 case AArch64::LDAPURSHWi:
4889 case AArch64::LDAPURSHXi:
4890 case AArch64::STURHi:
4891 case AArch64::STURHHi:
4892 case AArch64::STLURHi:
4893 case AArch64::ATOMIC_STORE_HINT_Hi:
4894 Scale = TypeSize::getFixed(1);
4895 Width = TypeSize::getFixed(2);
4896 MinOffset = -256;
4897 MaxOffset = 255;
4898 break;
4899 case AArch64::LDURBi:
4900 case AArch64::LDURBBi:
4901 case AArch64::LDURSBXi:
4902 case AArch64::LDURSBWi:
4903 case AArch64::LDAPURBi:
4904 case AArch64::LDAPURSBWi:
4905 case AArch64::LDAPURSBXi:
4906 case AArch64::STURBi:
4907 case AArch64::STURBBi:
4908 case AArch64::STLURBi:
4909 case AArch64::ATOMIC_STORE_HINT_Bi:
4910 Scale = Width = TypeSize::getFixed(1);
4911 MinOffset = -256;
4912 MaxOffset = 255;
4913 break;
4914 // LDP / STP (including pre/post inc)
4915 case AArch64::LDPQi:
4916 case AArch64::LDNPQi:
4917 case AArch64::STPQi:
4918 case AArch64::STNPQi:
4919 case AArch64::LDPQpost:
4920 case AArch64::LDPQpre:
4921 case AArch64::STPQpost:
4922 case AArch64::STPQpre:
4923 Scale = TypeSize::getFixed(16);
4924 Width = TypeSize::getFixed(16 * 2);
4925 MinOffset = -64;
4926 MaxOffset = 63;
4927 break;
4928 case AArch64::LDPXi:
4929 case AArch64::LDPDi:
4930 case AArch64::LDNPXi:
4931 case AArch64::LDNPDi:
4932 case AArch64::STPXi:
4933 case AArch64::STPDi:
4934 case AArch64::STNPXi:
4935 case AArch64::STNPDi:
4936 case AArch64::LDPDpost:
4937 case AArch64::LDPDpre:
4938 case AArch64::LDPXpost:
4939 case AArch64::LDPXpre:
4940 case AArch64::STPDpost:
4941 case AArch64::STPDpre:
4942 case AArch64::STPXpost:
4943 case AArch64::STPXpre:
4944 Scale = TypeSize::getFixed(8);
4945 Width = TypeSize::getFixed(8 * 2);
4946 MinOffset = -64;
4947 MaxOffset = 63;
4948 break;
4949 case AArch64::LDPWi:
4950 case AArch64::LDPSi:
4951 case AArch64::LDNPWi:
4952 case AArch64::LDNPSi:
4953 case AArch64::STPWi:
4954 case AArch64::STPSi:
4955 case AArch64::STNPWi:
4956 case AArch64::STNPSi:
4957 case AArch64::LDPSpost:
4958 case AArch64::LDPSpre:
4959 case AArch64::LDPWpost:
4960 case AArch64::LDPWpre:
4961 case AArch64::STPSpost:
4962 case AArch64::STPSpre:
4963 case AArch64::STPWpost:
4964 case AArch64::STPWpre:
4965 Scale = TypeSize::getFixed(4);
4966 Width = TypeSize::getFixed(4 * 2);
4967 MinOffset = -64;
4968 MaxOffset = 63;
4969 break;
4970 case AArch64::StoreSwiftAsyncContext:
4971 // Store is an STRXui, but there might be an ADDXri in the expansion too.
4972 Scale = TypeSize::getFixed(1);
4973 Width = TypeSize::getFixed(8);
4974 MinOffset = 0;
4975 MaxOffset = 4095;
4976 break;
4977 case AArch64::ADDG:
4978 Scale = TypeSize::getFixed(16);
4979 Width = TypeSize::getFixed(0);
4980 MinOffset = 0;
4981 MaxOffset = 63;
4982 break;
4983 case AArch64::TAGPstack:
4984 Scale = TypeSize::getFixed(16);
4985 Width = TypeSize::getFixed(0);
4986 // TAGP with a negative offset turns into SUBP, which has a maximum offset
4987 // of 63 (not 64!).
4988 MinOffset = -63;
4989 MaxOffset = 63;
4990 break;
4991 case AArch64::LDG:
4992 case AArch64::STGi:
4993 case AArch64::STGPreIndex:
4994 case AArch64::STGPostIndex:
4995 case AArch64::STZGi:
4996 case AArch64::STZGPreIndex:
4997 case AArch64::STZGPostIndex:
4998 Scale = Width = TypeSize::getFixed(16);
4999 MinOffset = -256;
5000 MaxOffset = 255;
5001 break;
5002 // SVE
5003 case AArch64::STR_ZZZZXI:
5004 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
5005 case AArch64::LDR_ZZZZXI:
5006 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
5007 Scale = TypeSize::getScalable(16);
5008 Width = TypeSize::getScalable(16 * 4);
5009 MinOffset = -256;
5010 MaxOffset = 252;
5011 break;
5012 case AArch64::STR_ZZZXI:
5013 case AArch64::LDR_ZZZXI:
5014 Scale = TypeSize::getScalable(16);
5015 Width = TypeSize::getScalable(16 * 3);
5016 MinOffset = -256;
5017 MaxOffset = 253;
5018 break;
5019 case AArch64::STR_ZZXI:
5020 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
5021 case AArch64::LDR_ZZXI:
5022 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
5023 Scale = TypeSize::getScalable(16);
5024 Width = TypeSize::getScalable(16 * 2);
5025 MinOffset = -256;
5026 MaxOffset = 254;
5027 break;
5028 case AArch64::LDR_PXI:
5029 case AArch64::STR_PXI:
5030 Scale = Width = TypeSize::getScalable(2);
5031 MinOffset = -256;
5032 MaxOffset = 255;
5033 break;
5034 case AArch64::LDR_PPXI:
5035 case AArch64::STR_PPXI:
5036 Scale = TypeSize::getScalable(2);
5037 Width = TypeSize::getScalable(2 * 2);
5038 MinOffset = -256;
5039 MaxOffset = 254;
5040 break;
5041 case AArch64::LDR_ZXI:
5042 case AArch64::STR_ZXI:
5043 Scale = Width = TypeSize::getScalable(16);
5044 MinOffset = -256;
5045 MaxOffset = 255;
5046 break;
5047 case AArch64::LD1B_IMM:
5048 case AArch64::LD1H_IMM:
5049 case AArch64::LD1W_IMM:
5050 case AArch64::LD1D_IMM:
5051 case AArch64::LDNT1B_ZRI:
5052 case AArch64::LDNT1H_ZRI:
5053 case AArch64::LDNT1W_ZRI:
5054 case AArch64::LDNT1D_ZRI:
5055 case AArch64::ST1B_IMM:
5056 case AArch64::ST1H_IMM:
5057 case AArch64::ST1W_IMM:
5058 case AArch64::ST1D_IMM:
5059 case AArch64::STNT1B_ZRI:
5060 case AArch64::STNT1H_ZRI:
5061 case AArch64::STNT1W_ZRI:
5062 case AArch64::STNT1D_ZRI:
5063 case AArch64::LDNF1B_IMM:
5064 case AArch64::LDNF1H_IMM:
5065 case AArch64::LDNF1W_IMM:
5066 case AArch64::LDNF1D_IMM:
5067 // A full vectors worth of data
5068 // Width = mbytes * elements
5069 Scale = Width = TypeSize::getScalable(16);
5070 MinOffset = -8;
5071 MaxOffset = 7;
5072 break;
5073 case AArch64::LD2B_IMM:
5074 case AArch64::LD2H_IMM:
5075 case AArch64::LD2W_IMM:
5076 case AArch64::LD2D_IMM:
5077 case AArch64::ST2B_IMM:
5078 case AArch64::ST2H_IMM:
5079 case AArch64::ST2W_IMM:
5080 case AArch64::ST2D_IMM:
5081 case AArch64::LD1B_2Z_IMM:
5082 case AArch64::LD1B_2Z_STRIDED_IMM:
5083 case AArch64::LD1H_2Z_IMM:
5084 case AArch64::LD1H_2Z_STRIDED_IMM:
5085 case AArch64::LD1W_2Z_IMM:
5086 case AArch64::LD1W_2Z_STRIDED_IMM:
5087 case AArch64::LD1D_2Z_IMM:
5088 case AArch64::LD1D_2Z_STRIDED_IMM:
5089 case AArch64::LD1B_2Z_IMM_PSEUDO:
5090 case AArch64::LD1H_2Z_IMM_PSEUDO:
5091 case AArch64::LD1W_2Z_IMM_PSEUDO:
5092 case AArch64::LD1D_2Z_IMM_PSEUDO:
5093 case AArch64::ST1B_2Z_IMM:
5094 case AArch64::ST1B_2Z_STRIDED_IMM:
5095 case AArch64::ST1H_2Z_IMM:
5096 case AArch64::ST1H_2Z_STRIDED_IMM:
5097 case AArch64::ST1W_2Z_IMM:
5098 case AArch64::ST1W_2Z_STRIDED_IMM:
5099 case AArch64::ST1D_2Z_IMM:
5100 case AArch64::ST1D_2Z_STRIDED_IMM:
5101 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
5102 case AArch64::LDNT1B_2Z_IMM:
5103 case AArch64::LDNT1B_2Z_STRIDED_IMM:
5104 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
5105 case AArch64::LDNT1H_2Z_IMM:
5106 case AArch64::LDNT1H_2Z_STRIDED_IMM:
5107 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
5108 case AArch64::LDNT1W_2Z_IMM:
5109 case AArch64::LDNT1W_2Z_STRIDED_IMM:
5110 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
5111 case AArch64::LDNT1D_2Z_IMM:
5112 case AArch64::LDNT1D_2Z_STRIDED_IMM:
5113 case AArch64::STNT1B_2Z_IMM:
5114 case AArch64::STNT1B_2Z_STRIDED_IMM:
5115 case AArch64::STNT1H_2Z_IMM:
5116 case AArch64::STNT1H_2Z_STRIDED_IMM:
5117 case AArch64::STNT1W_2Z_IMM:
5118 case AArch64::STNT1W_2Z_STRIDED_IMM:
5119 case AArch64::STNT1D_2Z_IMM:
5120 case AArch64::STNT1D_2Z_STRIDED_IMM:
5121 case AArch64::ST1B_2Z_IMM_PSEUDO:
5122 case AArch64::ST1H_2Z_IMM_PSEUDO:
5123 case AArch64::ST1W_2Z_IMM_PSEUDO:
5124 case AArch64::ST1D_2Z_IMM_PSEUDO:
5125 case AArch64::STNT1B_2Z_IMM_PSEUDO:
5126 case AArch64::STNT1H_2Z_IMM_PSEUDO:
5127 case AArch64::STNT1W_2Z_IMM_PSEUDO:
5128 case AArch64::STNT1D_2Z_IMM_PSEUDO:
5129 Scale = Width = TypeSize::getScalable(16 * 2);
5130 MinOffset = -8;
5131 MaxOffset = 7;
5132 break;
5133 case AArch64::LD3B_IMM:
5134 case AArch64::LD3H_IMM:
5135 case AArch64::LD3W_IMM:
5136 case AArch64::LD3D_IMM:
5137 case AArch64::ST3B_IMM:
5138 case AArch64::ST3H_IMM:
5139 case AArch64::ST3W_IMM:
5140 case AArch64::ST3D_IMM:
5141 Scale = Width = TypeSize::getScalable(16 * 3);
5142 MinOffset = -8;
5143 MaxOffset = 7;
5144 break;
5145 case AArch64::LD4B_IMM:
5146 case AArch64::LD4H_IMM:
5147 case AArch64::LD4W_IMM:
5148 case AArch64::LD4D_IMM:
5149 case AArch64::ST4B_IMM:
5150 case AArch64::ST4H_IMM:
5151 case AArch64::ST4W_IMM:
5152 case AArch64::ST4D_IMM:
5153 case AArch64::LD1B_4Z_IMM:
5154 case AArch64::LD1B_4Z_STRIDED_IMM:
5155 case AArch64::LD1H_4Z_IMM:
5156 case AArch64::LD1H_4Z_STRIDED_IMM:
5157 case AArch64::LD1W_4Z_IMM:
5158 case AArch64::LD1W_4Z_STRIDED_IMM:
5159 case AArch64::LD1D_4Z_IMM:
5160 case AArch64::LD1D_4Z_STRIDED_IMM:
5161 case AArch64::LD1B_4Z_IMM_PSEUDO:
5162 case AArch64::LD1H_4Z_IMM_PSEUDO:
5163 case AArch64::LD1W_4Z_IMM_PSEUDO:
5164 case AArch64::LD1D_4Z_IMM_PSEUDO:
5165 case AArch64::ST1B_4Z_IMM:
5166 case AArch64::ST1B_4Z_STRIDED_IMM:
5167 case AArch64::ST1H_4Z_IMM:
5168 case AArch64::ST1H_4Z_STRIDED_IMM:
5169 case AArch64::ST1W_4Z_IMM:
5170 case AArch64::ST1W_4Z_STRIDED_IMM:
5171 case AArch64::ST1D_4Z_IMM:
5172 case AArch64::ST1D_4Z_STRIDED_IMM:
5173 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
5174 case AArch64::LDNT1B_4Z_IMM:
5175 case AArch64::LDNT1B_4Z_STRIDED_IMM:
5176 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
5177 case AArch64::LDNT1H_4Z_IMM:
5178 case AArch64::LDNT1H_4Z_STRIDED_IMM:
5179 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
5180 case AArch64::LDNT1W_4Z_IMM:
5181 case AArch64::LDNT1W_4Z_STRIDED_IMM:
5182 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
5183 case AArch64::LDNT1D_4Z_IMM:
5184 case AArch64::LDNT1D_4Z_STRIDED_IMM:
5185 case AArch64::STNT1B_4Z_IMM:
5186 case AArch64::STNT1B_4Z_STRIDED_IMM:
5187 case AArch64::STNT1H_4Z_IMM:
5188 case AArch64::STNT1H_4Z_STRIDED_IMM:
5189 case AArch64::STNT1W_4Z_IMM:
5190 case AArch64::STNT1W_4Z_STRIDED_IMM:
5191 case AArch64::STNT1D_4Z_IMM:
5192 case AArch64::STNT1D_4Z_STRIDED_IMM:
5193 case AArch64::ST1B_4Z_IMM_PSEUDO:
5194 case AArch64::ST1H_4Z_IMM_PSEUDO:
5195 case AArch64::ST1W_4Z_IMM_PSEUDO:
5196 case AArch64::ST1D_4Z_IMM_PSEUDO:
5197 case AArch64::STNT1B_4Z_IMM_PSEUDO:
5198 case AArch64::STNT1H_4Z_IMM_PSEUDO:
5199 case AArch64::STNT1W_4Z_IMM_PSEUDO:
5200 case AArch64::STNT1D_4Z_IMM_PSEUDO:
5201 Scale = Width = TypeSize::getScalable(16 * 4);
5202 MinOffset = -8;
5203 MaxOffset = 7;
5204 break;
5205 case AArch64::LD1B_H_IMM:
5206 case AArch64::LD1SB_H_IMM:
5207 case AArch64::LD1H_S_IMM:
5208 case AArch64::LD1SH_S_IMM:
5209 case AArch64::LD1W_D_IMM:
5210 case AArch64::LD1SW_D_IMM:
5211 case AArch64::ST1B_H_IMM:
5212 case AArch64::ST1H_S_IMM:
5213 case AArch64::ST1W_D_IMM:
5214 case AArch64::LDNF1B_H_IMM:
5215 case AArch64::LDNF1SB_H_IMM:
5216 case AArch64::LDNF1H_S_IMM:
5217 case AArch64::LDNF1SH_S_IMM:
5218 case AArch64::LDNF1W_D_IMM:
5219 case AArch64::LDNF1SW_D_IMM:
5220 // A half vector worth of data
5221 // Width = mbytes * elements
5222 Scale = Width = TypeSize::getScalable(8);
5223 MinOffset = -8;
5224 MaxOffset = 7;
5225 break;
5226 case AArch64::LD1B_S_IMM:
5227 case AArch64::LD1SB_S_IMM:
5228 case AArch64::LD1H_D_IMM:
5229 case AArch64::LD1SH_D_IMM:
5230 case AArch64::ST1B_S_IMM:
5231 case AArch64::ST1H_D_IMM:
5232 case AArch64::LDNF1B_S_IMM:
5233 case AArch64::LDNF1SB_S_IMM:
5234 case AArch64::LDNF1H_D_IMM:
5235 case AArch64::LDNF1SH_D_IMM:
5236 // A quarter vector worth of data
5237 // Width = mbytes * elements
5238 Scale = Width = TypeSize::getScalable(4);
5239 MinOffset = -8;
5240 MaxOffset = 7;
5241 break;
5242 case AArch64::LD1B_D_IMM:
5243 case AArch64::LD1SB_D_IMM:
5244 case AArch64::ST1B_D_IMM:
5245 case AArch64::LDNF1B_D_IMM:
5246 case AArch64::LDNF1SB_D_IMM:
5247 // A eighth vector worth of data
5248 // Width = mbytes * elements
5249 Scale = Width = TypeSize::getScalable(2);
5250 MinOffset = -8;
5251 MaxOffset = 7;
5252 break;
5253 case AArch64::ST2Gi:
5254 case AArch64::ST2GPreIndex:
5255 case AArch64::ST2GPostIndex:
5256 case AArch64::STZ2Gi:
5257 case AArch64::STZ2GPreIndex:
5258 case AArch64::STZ2GPostIndex:
5259 Scale = TypeSize::getFixed(16);
5260 Width = TypeSize::getFixed(32);
5261 MinOffset = -256;
5262 MaxOffset = 255;
5263 break;
5264 case AArch64::STGPi:
5265 case AArch64::STGPpost:
5266 case AArch64::STGPpre:
5267 Scale = Width = TypeSize::getFixed(16);
5268 MinOffset = -64;
5269 MaxOffset = 63;
5270 break;
5271 case AArch64::LD1RB_IMM:
5272 case AArch64::LD1RB_H_IMM:
5273 case AArch64::LD1RB_S_IMM:
5274 case AArch64::LD1RB_D_IMM:
5275 case AArch64::LD1RSB_H_IMM:
5276 case AArch64::LD1RSB_S_IMM:
5277 case AArch64::LD1RSB_D_IMM:
5278 Scale = Width = TypeSize::getFixed(1);
5279 MinOffset = 0;
5280 MaxOffset = 63;
5281 break;
5282 case AArch64::LD1RH_IMM:
5283 case AArch64::LD1RH_S_IMM:
5284 case AArch64::LD1RH_D_IMM:
5285 case AArch64::LD1RSH_S_IMM:
5286 case AArch64::LD1RSH_D_IMM:
5287 Scale = Width = TypeSize::getFixed(2);
5288 MinOffset = 0;
5289 MaxOffset = 63;
5290 break;
5291 case AArch64::LD1RW_IMM:
5292 case AArch64::LD1RW_D_IMM:
5293 case AArch64::LD1RSW_IMM:
5294 Scale = Width = TypeSize::getFixed(4);
5295 MinOffset = 0;
5296 MaxOffset = 63;
5297 break;
5298 case AArch64::LD1RD_IMM:
5299 Scale = Width = TypeSize::getFixed(8);
5300 MinOffset = 0;
5301 MaxOffset = 63;
5302 break;
5303 }
5304
5305 return true;
5306}
5307
5308// Scaling factor for unscaled load or store.
5310 switch (Opc) {
5311 default:
5312 llvm_unreachable("Opcode has unknown scale!");
5313 case AArch64::LDRBui:
5314 case AArch64::LDRBBui:
5315 case AArch64::LDURBBi:
5316 case AArch64::LDRSBWui:
5317 case AArch64::LDURSBWi:
5318 case AArch64::STRBui:
5319 case AArch64::STRBBui:
5320 case AArch64::STURBBi:
5321 return 1;
5322 case AArch64::LDRHui:
5323 case AArch64::LDRHHui:
5324 case AArch64::LDURHHi:
5325 case AArch64::LDRSHWui:
5326 case AArch64::LDURSHWi:
5327 case AArch64::STRHui:
5328 case AArch64::STRHHui:
5329 case AArch64::STURHHi:
5330 return 2;
5331 case AArch64::LDRSui:
5332 case AArch64::LDURSi:
5333 case AArch64::LDRSpre:
5334 case AArch64::LDRSWui:
5335 case AArch64::LDURSWi:
5336 case AArch64::LDRSWpre:
5337 case AArch64::LDRWpre:
5338 case AArch64::LDRWui:
5339 case AArch64::LDURWi:
5340 case AArch64::STRSui:
5341 case AArch64::STURSi:
5342 case AArch64::STRSpre:
5343 case AArch64::STRWui:
5344 case AArch64::STURWi:
5345 case AArch64::STRWpre:
5346 case AArch64::LDPSi:
5347 case AArch64::LDPSWi:
5348 case AArch64::LDPWi:
5349 case AArch64::STPSi:
5350 case AArch64::STPWi:
5351 return 4;
5352 case AArch64::LDRDui:
5353 case AArch64::LDURDi:
5354 case AArch64::LDRDpre:
5355 case AArch64::LDRXui:
5356 case AArch64::LDURXi:
5357 case AArch64::LDRXpre:
5358 case AArch64::STRDui:
5359 case AArch64::STURDi:
5360 case AArch64::STRDpre:
5361 case AArch64::STRXui:
5362 case AArch64::STURXi:
5363 case AArch64::STRXpre:
5364 case AArch64::LDPDi:
5365 case AArch64::LDPXi:
5366 case AArch64::STPDi:
5367 case AArch64::STPXi:
5368 return 8;
5369 case AArch64::LDRQui:
5370 case AArch64::LDURQi:
5371 case AArch64::STRQui:
5372 case AArch64::STURQi:
5373 case AArch64::STRQpre:
5374 case AArch64::LDPQi:
5375 case AArch64::LDRQpre:
5376 case AArch64::STPQi:
5377 case AArch64::STGi:
5378 case AArch64::STZGi:
5379 case AArch64::ST2Gi:
5380 case AArch64::STZ2Gi:
5381 case AArch64::STGPi:
5382 return 16;
5383 }
5384}
5385
5387 switch (MI.getOpcode()) {
5388 default:
5389 return false;
5390 case AArch64::LDRWpre:
5391 case AArch64::LDRXpre:
5392 case AArch64::LDRSWpre:
5393 case AArch64::LDRSpre:
5394 case AArch64::LDRDpre:
5395 case AArch64::LDRQpre:
5396 return true;
5397 }
5398}
5399
5401 switch (MI.getOpcode()) {
5402 default:
5403 return false;
5404 case AArch64::STRWpre:
5405 case AArch64::STRXpre:
5406 case AArch64::STRSpre:
5407 case AArch64::STRDpre:
5408 case AArch64::STRQpre:
5409 return true;
5410 }
5411}
5412
5414 return isPreLd(MI) || isPreSt(MI);
5415}
5416
5418 switch (MI.getOpcode()) {
5419 default:
5420 return false;
5421 case AArch64::LDURBBi:
5422 case AArch64::LDURHHi:
5423 case AArch64::LDURWi:
5424 case AArch64::LDRBBui:
5425 case AArch64::LDRHHui:
5426 case AArch64::LDRWui:
5427 case AArch64::LDRBBroX:
5428 case AArch64::LDRHHroX:
5429 case AArch64::LDRWroX:
5430 case AArch64::LDRBBroW:
5431 case AArch64::LDRHHroW:
5432 case AArch64::LDRWroW:
5433 return true;
5434 }
5435}
5436
5438 switch (MI.getOpcode()) {
5439 default:
5440 return false;
5441 case AArch64::LDURSBWi:
5442 case AArch64::LDURSHWi:
5443 case AArch64::LDURSBXi:
5444 case AArch64::LDURSHXi:
5445 case AArch64::LDURSWi:
5446 case AArch64::LDRSBWui:
5447 case AArch64::LDRSHWui:
5448 case AArch64::LDRSBXui:
5449 case AArch64::LDRSHXui:
5450 case AArch64::LDRSWui:
5451 case AArch64::LDRSBWroX:
5452 case AArch64::LDRSHWroX:
5453 case AArch64::LDRSBXroX:
5454 case AArch64::LDRSHXroX:
5455 case AArch64::LDRSWroX:
5456 case AArch64::LDRSBWroW:
5457 case AArch64::LDRSHWroW:
5458 case AArch64::LDRSBXroW:
5459 case AArch64::LDRSHXroW:
5460 case AArch64::LDRSWroW:
5461 return true;
5462 }
5463}
5464
5466 switch (MI.getOpcode()) {
5467 default:
5468 return false;
5469 case AArch64::LDPSi:
5470 case AArch64::LDPSWi:
5471 case AArch64::LDPDi:
5472 case AArch64::LDPQi:
5473 case AArch64::LDPWi:
5474 case AArch64::LDPXi:
5475 case AArch64::STPSi:
5476 case AArch64::STPDi:
5477 case AArch64::STPQi:
5478 case AArch64::STPWi:
5479 case AArch64::STPXi:
5480 case AArch64::STGPi:
5481 return true;
5482 }
5483}
5484
5486 assert(MI.mayLoadOrStore() && "Load or store instruction expected");
5487 unsigned Idx =
5489 : 1;
5490 return MI.getOperand(Idx);
5491}
5492
5493const MachineOperand &
5495 assert(MI.mayLoadOrStore() && "Load or store instruction expected");
5496 unsigned Idx =
5498 : 2;
5499 return MI.getOperand(Idx);
5500}
5501
5502const MachineOperand &
5504 switch (MI.getOpcode()) {
5505 default:
5506 llvm_unreachable("Unexpected opcode");
5507 case AArch64::LDRBroX:
5508 case AArch64::LDRBBroX:
5509 case AArch64::LDRSBXroX:
5510 case AArch64::LDRSBWroX:
5511 case AArch64::LDRHroX:
5512 case AArch64::LDRHHroX:
5513 case AArch64::LDRSHXroX:
5514 case AArch64::LDRSHWroX:
5515 case AArch64::LDRWroX:
5516 case AArch64::LDRSroX:
5517 case AArch64::LDRSWroX:
5518 case AArch64::LDRDroX:
5519 case AArch64::LDRXroX:
5520 case AArch64::LDRQroX:
5521 return MI.getOperand(4);
5522 }
5523}
5524
5526 Register Reg) {
5527 if (MI.getParent() == nullptr)
5528 return nullptr;
5529 const MachineFunction *MF = MI.getParent()->getParent();
5530 return MF ? MF->getRegInfo().getRegClassOrNull(Reg) : nullptr;
5531}
5532
5534 auto IsHFPR = [&](const MachineOperand &Op) {
5535 if (!Op.isReg())
5536 return false;
5537 auto Reg = Op.getReg();
5538 if (Reg.isPhysical())
5539 return AArch64::FPR16RegClass.contains(Reg);
5540 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5541 return TRC == &AArch64::FPR16RegClass ||
5542 TRC == &AArch64::FPR16_loRegClass;
5543 };
5544 return llvm::any_of(MI.operands(), IsHFPR);
5545}
5546
5548 auto IsQFPR = [&](const MachineOperand &Op) {
5549 if (!Op.isReg())
5550 return false;
5551 auto Reg = Op.getReg();
5552 if (Reg.isPhysical())
5553 return AArch64::FPR128RegClass.contains(Reg);
5554 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5555 return TRC == &AArch64::FPR128RegClass ||
5556 TRC == &AArch64::FPR128_loRegClass;
5557 };
5558 return llvm::any_of(MI.operands(), IsQFPR);
5559}
5560
5562 switch (MI.getOpcode()) {
5563 case AArch64::BRK:
5564 case AArch64::HLT:
5565 case AArch64::PACIASP:
5566 case AArch64::PACIBSP:
5567 // Implicit BTI behavior.
5568 return true;
5569 case AArch64::PAUTH_PROLOGUE:
5570 // PAUTH_PROLOGUE expands to PACI(A|B)SP.
5571 return true;
5572 case AArch64::HINT: {
5573 unsigned Imm = MI.getOperand(0).getImm();
5574 // Explicit BTI instruction.
5575 if (Imm == 32 || Imm == 34 || Imm == 36 || Imm == 38)
5576 return true;
5577 // PACI(A|B)SP instructions.
5578 if (Imm == 25 || Imm == 27)
5579 return true;
5580 return false;
5581 }
5582 default:
5583 return false;
5584 }
5585}
5586
5588 if (Reg == 0)
5589 return false;
5590 assert(Reg.isPhysical() && "Expected physical register in isFpOrNEON");
5591 return AArch64::FPR128RegClass.contains(Reg) ||
5592 AArch64::FPR64RegClass.contains(Reg) ||
5593 AArch64::FPR32RegClass.contains(Reg) ||
5594 AArch64::FPR16RegClass.contains(Reg) ||
5595 AArch64::FPR8RegClass.contains(Reg);
5596}
5597
5599 auto IsFPR = [&](const MachineOperand &Op) {
5600 if (!Op.isReg())
5601 return false;
5602 auto Reg = Op.getReg();
5603 if (Reg.isPhysical())
5604 return isFpOrNEON(Reg);
5605
5606 const TargetRegisterClass *TRC = ::getRegClass(MI, Reg);
5607 return TRC == &AArch64::FPR128RegClass ||
5608 TRC == &AArch64::FPR128_loRegClass ||
5609 TRC == &AArch64::FPR64RegClass ||
5610 TRC == &AArch64::FPR64_loRegClass ||
5611 TRC == &AArch64::FPR32RegClass || TRC == &AArch64::FPR16RegClass ||
5612 TRC == &AArch64::FPR8RegClass;
5613 };
5614 return llvm::any_of(MI.operands(), IsFPR);
5615}
5616
5617// Scale the unscaled offsets. Returns false if the unscaled offset can't be
5618// scaled.
5619static bool scaleOffset(unsigned Opc, int64_t &Offset) {
5621
5622 // If the byte-offset isn't a multiple of the stride, we can't scale this
5623 // offset.
5624 if (Offset % Scale != 0)
5625 return false;
5626
5627 // Convert the byte-offset used by unscaled into an "element" offset used
5628 // by the scaled pair load/store instructions.
5629 Offset /= Scale;
5630 return true;
5631}
5632
5633static bool canPairLdStOpc(unsigned FirstOpc, unsigned SecondOpc) {
5634 if (FirstOpc == SecondOpc)
5635 return true;
5636 // We can also pair sign-ext and zero-ext instructions.
5637 switch (FirstOpc) {
5638 default:
5639 return false;
5640 case AArch64::STRSui:
5641 case AArch64::STURSi:
5642 return SecondOpc == AArch64::STRSui || SecondOpc == AArch64::STURSi;
5643 case AArch64::STRDui:
5644 case AArch64::STURDi:
5645 return SecondOpc == AArch64::STRDui || SecondOpc == AArch64::STURDi;
5646 case AArch64::STRQui:
5647 case AArch64::STURQi:
5648 return SecondOpc == AArch64::STRQui || SecondOpc == AArch64::STURQi;
5649 case AArch64::STRWui:
5650 case AArch64::STURWi:
5651 return SecondOpc == AArch64::STRWui || SecondOpc == AArch64::STURWi;
5652 case AArch64::STRXui:
5653 case AArch64::STURXi:
5654 return SecondOpc == AArch64::STRXui || SecondOpc == AArch64::STURXi;
5655 case AArch64::LDRSui:
5656 case AArch64::LDURSi:
5657 return SecondOpc == AArch64::LDRSui || SecondOpc == AArch64::LDURSi;
5658 case AArch64::LDRDui:
5659 case AArch64::LDURDi:
5660 return SecondOpc == AArch64::LDRDui || SecondOpc == AArch64::LDURDi;
5661 case AArch64::LDRQui:
5662 case AArch64::LDURQi:
5663 return SecondOpc == AArch64::LDRQui || SecondOpc == AArch64::LDURQi;
5664 case AArch64::LDRWui:
5665 case AArch64::LDURWi:
5666 return SecondOpc == AArch64::LDRSWui || SecondOpc == AArch64::LDURSWi;
5667 case AArch64::LDRSWui:
5668 case AArch64::LDURSWi:
5669 return SecondOpc == AArch64::LDRWui || SecondOpc == AArch64::LDURWi;
5670 case AArch64::LDRXui:
5671 case AArch64::LDURXi:
5672 return SecondOpc == AArch64::LDRXui || SecondOpc == AArch64::LDURXi;
5673 }
5674 // These instructions can't be paired based on their opcodes.
5675 return false;
5676}
5677
5678static bool shouldClusterFI(const MachineFrameInfo &MFI, int FI1,
5679 int64_t Offset1, unsigned Opcode1, int FI2,
5680 int64_t Offset2, unsigned Opcode2) {
5681 // Accesses through fixed stack object frame indices may access a different
5682 // fixed stack slot. Check that the object offsets + offsets match.
5683 if (MFI.isFixedObjectIndex(FI1) && MFI.isFixedObjectIndex(FI2)) {
5684 int64_t ObjectOffset1 = MFI.getObjectOffset(FI1);
5685 int64_t ObjectOffset2 = MFI.getObjectOffset(FI2);
5686 assert(ObjectOffset1 <= ObjectOffset2 && "Object offsets are not ordered.");
5687 // Convert to scaled object offsets.
5688 int Scale1 = AArch64InstrInfo::getMemScale(Opcode1);
5689 if (ObjectOffset1 % Scale1 != 0)
5690 return false;
5691 ObjectOffset1 /= Scale1;
5692 int Scale2 = AArch64InstrInfo::getMemScale(Opcode2);
5693 if (ObjectOffset2 % Scale2 != 0)
5694 return false;
5695 ObjectOffset2 /= Scale2;
5696 ObjectOffset1 += Offset1;
5697 ObjectOffset2 += Offset2;
5698 return ObjectOffset1 + 1 == ObjectOffset2;
5699 }
5700
5701 return FI1 == FI2;
5702}
5703
5704/// Detect opportunities for ldp/stp formation.
5705///
5706/// Only called for LdSt for which getMemOperandWithOffset returns true.
5708 ArrayRef<const MachineOperand *> BaseOps1, int64_t OpOffset1,
5709 bool OffsetIsScalable1, ArrayRef<const MachineOperand *> BaseOps2,
5710 int64_t OpOffset2, bool OffsetIsScalable2, unsigned ClusterSize,
5711 unsigned NumBytes) const {
5712 assert(BaseOps1.size() == 1 && BaseOps2.size() == 1);
5713 const MachineOperand &BaseOp1 = *BaseOps1.front();
5714 const MachineOperand &BaseOp2 = *BaseOps2.front();
5715 const MachineInstr &FirstLdSt = *BaseOp1.getParent();
5716 const MachineInstr &SecondLdSt = *BaseOp2.getParent();
5717 if (BaseOp1.getType() != BaseOp2.getType())
5718 return false;
5719
5720 assert((BaseOp1.isReg() || BaseOp1.isFI()) &&
5721 "Only base registers and frame indices are supported.");
5722
5723 // Check for both base regs and base FI.
5724 if (BaseOp1.isReg() && BaseOp1.getReg() != BaseOp2.getReg())
5725 return false;
5726
5727 // Only cluster up to a single pair.
5728 if (ClusterSize > 2)
5729 return false;
5730
5731 if (!isPairableLdStInst(FirstLdSt) || !isPairableLdStInst(SecondLdSt))
5732 return false;
5733
5734 // Can we pair these instructions based on their opcodes?
5735 unsigned FirstOpc = FirstLdSt.getOpcode();
5736 unsigned SecondOpc = SecondLdSt.getOpcode();
5737 if (!canPairLdStOpc(FirstOpc, SecondOpc))
5738 return false;
5739
5740 // Can't merge volatiles or load/stores that have a hint to avoid pair
5741 // formation, for example.
5742 if (!isCandidateToMergeOrPair(FirstLdSt) ||
5743 !isCandidateToMergeOrPair(SecondLdSt))
5744 return false;
5745
5746 // isCandidateToMergeOrPair guarantees that operand 2 is an immediate.
5747 int64_t Offset1 = FirstLdSt.getOperand(2).getImm();
5748 if (hasUnscaledLdStOffset(FirstOpc) && !scaleOffset(FirstOpc, Offset1))
5749 return false;
5750
5751 int64_t Offset2 = SecondLdSt.getOperand(2).getImm();
5752 if (hasUnscaledLdStOffset(SecondOpc) && !scaleOffset(SecondOpc, Offset2))
5753 return false;
5754
5755 // Pairwise instructions have a 7-bit signed offset field.
5756 if (Offset1 > 63 || Offset1 < -64)
5757 return false;
5758
5759 // The caller should already have ordered First/SecondLdSt by offset.
5760 // Note: except for non-equal frame index bases
5761 if (BaseOp1.isFI()) {
5762 assert((!BaseOp1.isIdenticalTo(BaseOp2) || Offset1 <= Offset2) &&
5763 "Caller should have ordered offsets.");
5764
5765 const MachineFrameInfo &MFI =
5766 FirstLdSt.getParent()->getParent()->getFrameInfo();
5767 return shouldClusterFI(MFI, BaseOp1.getIndex(), Offset1, FirstOpc,
5768 BaseOp2.getIndex(), Offset2, SecondOpc);
5769 }
5770
5771 assert(Offset1 <= Offset2 && "Caller should have ordered offsets.");
5772
5773 return Offset1 + 1 == Offset2;
5774}
5775
5777 MCRegister Reg, unsigned SubIdx,
5778 RegState State,
5779 const TargetRegisterInfo *TRI) {
5780 if (!SubIdx)
5781 return MIB.addReg(Reg, State);
5782
5783 if (Reg.isPhysical())
5784 return MIB.addReg(TRI->getSubReg(Reg, SubIdx), State);
5785 return MIB.addReg(Reg, State, SubIdx);
5786}
5787
5790 const DebugLoc &DL, MCRegister DestReg,
5791 MCRegister SrcReg, bool KillSrc,
5792 ArrayRef<unsigned> Indices) const {
5793 assert(Subtarget.hasNEON() && "Unexpected register copy without NEON");
5795 uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
5796 uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
5797 unsigned NumRegs = Indices.size();
5798 MCRegister DestSubReg = TRI->getSubReg(DestReg, Indices[0]);
5799 assert(!AArch64::PNRRegClass.contains(DestSubReg) &&
5800 "Unexpected predicate tuple copy");
5801 unsigned MaxRegs = AArch64::PPRRegClass.contains(DestSubReg) ? 15 : 31;
5802
5803 int SubReg = 0, End = NumRegs, Incr = 1;
5804 // Copy in reverse if a forward copy will clobber the tuple
5805 if (((DestEncoding - SrcEncoding) & MaxRegs) < NumRegs) {
5806 SubReg = NumRegs - 1;
5807 End = -1;
5808 Incr = -1;
5809 }
5810
5811 for (; SubReg != End; SubReg += Incr) {
5812 DestSubReg = TRI->getSubReg(DestReg, Indices[SubReg]);
5813 MCRegister SrcSubReg = TRI->getSubReg(SrcReg, Indices[SubReg]);
5814 copyPhysRegImpl(MBB, I, DL, DestSubReg, SrcSubReg, KillSrc);
5815 }
5816}
5817
5820 const DebugLoc &DL, MCRegister DestReg,
5821 MCRegister SrcReg, bool KillSrc,
5822 unsigned Opcode, unsigned ZeroReg,
5823 llvm::ArrayRef<unsigned> Indices) const {
5825 unsigned NumRegs = Indices.size();
5826
5827#ifndef NDEBUG
5828 uint16_t DestEncoding = TRI->getEncodingValue(DestReg);
5829 uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg);
5830 assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 &&
5831 "GPR reg sequences should not be able to overlap");
5832#endif
5833
5834 for (unsigned SubReg = 0; SubReg != NumRegs; ++SubReg) {
5835 const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode));
5836 AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI);
5837 MIB.addReg(ZeroReg);
5838 AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI);
5839 MIB.addImm(0);
5840 }
5841}
5842
5843/// Returns true if the instruction at I is in a streaming call site region,
5844/// within a single basic block.
5845/// A "call site streaming region" starts after smstart and ends at smstop
5846/// around a call to a streaming function. This walks backward from I.
5849 MachineFunction &MF = *MBB.getParent();
5851 if (!AFI->hasStreamingModeChanges())
5852 return false;
5853 // Walk backwards to find smstart/smstop
5854 for (MachineInstr &MI : reverse(make_range(MBB.begin(), I))) {
5855 unsigned Opc = MI.getOpcode();
5856 if (Opc == AArch64::MSRpstatesvcrImm1 || Opc == AArch64::MSRpstatePseudo) {
5857 // Check if this is SM change (not ZA)
5858 int64_t PState = MI.getOperand(0).getImm();
5859 if (PState == AArch64SVCR::SVCRSM || PState == AArch64SVCR::SVCRSMZA) {
5860 // Operand 1 is 1 for start, 0 for stop
5861 return MI.getOperand(1).getImm() == 1;
5862 }
5863 }
5864 }
5865 return false;
5866}
5867
5868/// Returns true if in a streaming call site region without SME-FA64.
5869static bool mustAvoidNeonAtMBBI(const AArch64Subtarget &Subtarget,
5872 return !Subtarget.hasSMEFA64() && isInStreamingCallSiteRegion(MBB, I);
5873}
5874
5877 const DebugLoc &DL, Register DestReg,
5878 Register SrcReg, bool KillSrc,
5879 bool RenamableDest,
5880 bool RenamableSrc) const {
5881 if (AArch64::GPR32spRegClass.contains(DestReg) &&
5882 AArch64::GPR32spRegClass.contains(SrcReg)) {
5883 if (DestReg == AArch64::WSP || SrcReg == AArch64::WSP) {
5884 // If either operand is WSP, expand to ADD #0.
5885 if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5886 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5887 // Cyclone recognizes "ADD Xd, Xn, #0" as a zero-cycle register move.
5888 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5889 &AArch64::GPR64spRegClass);
5890 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5891 &AArch64::GPR64spRegClass);
5892 // This instruction is reading and writing X registers. This may upset
5893 // the register scavenger and machine verifier, so we need to indicate
5894 // that we are reading an undefined value from SrcRegX, but a proper
5895 // value from SrcReg.
5896 BuildMI(MBB, I, DL, get(AArch64::ADDXri), DestRegX)
5897 .addReg(SrcRegX, RegState::Undef)
5898 .addImm(0)
5900 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
5901 ++NumZCRegMoveInstrsGPR;
5902 } else {
5903 BuildMI(MBB, I, DL, get(AArch64::ADDWri), DestReg)
5904 .addReg(SrcReg, getKillRegState(KillSrc))
5905 .addImm(0)
5907 if (Subtarget.hasZeroCycleRegMoveGPR32())
5908 ++NumZCRegMoveInstrsGPR;
5909 }
5910 } else if (Subtarget.hasZeroCycleRegMoveGPR64() &&
5911 !Subtarget.hasZeroCycleRegMoveGPR32()) {
5912 // Cyclone recognizes "ORR Xd, XZR, Xm" as a zero-cycle register move.
5913 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5914 &AArch64::GPR64spRegClass);
5915 assert(DestRegX.isValid() && "Destination super-reg not valid");
5916 MCRegister SrcRegX = RI.getMatchingSuperReg(SrcReg, AArch64::sub_32,
5917 &AArch64::GPR64spRegClass);
5918 assert(SrcRegX.isValid() && "Source super-reg not valid");
5919 // This instruction is reading and writing X registers. This may upset
5920 // the register scavenger and machine verifier, so we need to indicate
5921 // that we are reading an undefined value from SrcRegX, but a proper
5922 // value from SrcReg.
5923 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestRegX)
5924 .addReg(AArch64::XZR)
5925 .addReg(SrcRegX, RegState::Undef)
5926 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
5927 ++NumZCRegMoveInstrsGPR;
5928 } else {
5929 // Otherwise, expand to ORR WZR.
5930 BuildMI(MBB, I, DL, get(AArch64::ORRWrr), DestReg)
5931 .addReg(AArch64::WZR)
5932 .addReg(SrcReg, getKillRegState(KillSrc));
5933 if (Subtarget.hasZeroCycleRegMoveGPR32())
5934 ++NumZCRegMoveInstrsGPR;
5935 }
5936 return;
5937 }
5938
5939 // GPR32 zeroing
5940 if (AArch64::GPR32spRegClass.contains(DestReg) && SrcReg == AArch64::WZR) {
5941 if (Subtarget.hasZeroCycleZeroingGPR64() &&
5942 !Subtarget.hasZeroCycleZeroingGPR32()) {
5943 MCRegister DestRegX = RI.getMatchingSuperReg(DestReg, AArch64::sub_32,
5944 &AArch64::GPR64spRegClass);
5945 assert(DestRegX.isValid() && "Destination super-reg not valid");
5946 BuildMI(MBB, I, DL, get(AArch64::MOVZXi), DestRegX)
5947 .addImm(0)
5949 ++NumZCZeroingInstrsGPR;
5950 } else if (Subtarget.hasZeroCycleZeroingGPR32()) {
5951 BuildMI(MBB, I, DL, get(AArch64::MOVZWi), DestReg)
5952 .addImm(0)
5954 ++NumZCZeroingInstrsGPR;
5955 } else {
5956 BuildMI(MBB, I, DL, get(AArch64::ORRWrr), DestReg)
5957 .addReg(AArch64::WZR)
5958 .addReg(AArch64::WZR);
5959 }
5960 return;
5961 }
5962
5963 if (AArch64::GPR64spRegClass.contains(DestReg) &&
5964 AArch64::GPR64spRegClass.contains(SrcReg)) {
5965 if (DestReg == AArch64::SP || SrcReg == AArch64::SP) {
5966 // If either operand is SP, expand to ADD #0.
5967 BuildMI(MBB, I, DL, get(AArch64::ADDXri), DestReg)
5968 .addReg(SrcReg, getKillRegState(KillSrc))
5969 .addImm(0)
5971 if (Subtarget.hasZeroCycleRegMoveGPR64())
5972 ++NumZCRegMoveInstrsGPR;
5973 } else {
5974 // Otherwise, expand to ORR XZR.
5975 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestReg)
5976 .addReg(AArch64::XZR)
5977 .addReg(SrcReg, getKillRegState(KillSrc));
5978 if (Subtarget.hasZeroCycleRegMoveGPR64())
5979 ++NumZCRegMoveInstrsGPR;
5980 }
5981 return;
5982 }
5983
5984 // GPR64 zeroing
5985 if (AArch64::GPR64spRegClass.contains(DestReg) && SrcReg == AArch64::XZR) {
5986 if (Subtarget.hasZeroCycleZeroingGPR64()) {
5987 BuildMI(MBB, I, DL, get(AArch64::MOVZXi), DestReg)
5988 .addImm(0)
5990 ++NumZCZeroingInstrsGPR;
5991 } else {
5992 BuildMI(MBB, I, DL, get(AArch64::ORRXrr), DestReg)
5993 .addReg(AArch64::XZR)
5994 .addReg(AArch64::XZR);
5995 }
5996 return;
5997 }
5998
5999 // Copy a Predicate register by ORRing with itself.
6000 if (AArch64::PPRRegClass.contains(DestReg) &&
6001 AArch64::PPRRegClass.contains(SrcReg)) {
6002 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6003 "Unexpected SVE register.");
6004 BuildMI(MBB, I, DL, get(AArch64::ORR_PPzPP), DestReg)
6005 .addReg(SrcReg) // Pg
6006 .addReg(SrcReg)
6007 .addReg(SrcReg, getKillRegState(KillSrc));
6008 return;
6009 }
6010
6011 // Copy a predicate-as-counter register by ORRing with itself as if it
6012 // were a regular predicate (mask) register.
6013 bool DestIsPNR = AArch64::PNRRegClass.contains(DestReg);
6014 bool SrcIsPNR = AArch64::PNRRegClass.contains(SrcReg);
6015 if (DestIsPNR || SrcIsPNR) {
6016 auto ToPPR = [](MCRegister R) -> MCRegister {
6017 return (R - AArch64::PN0) + AArch64::P0;
6018 };
6019 MCRegister PPRSrcReg = SrcIsPNR ? ToPPR(SrcReg) : SrcReg.asMCReg();
6020 MCRegister PPRDestReg = DestIsPNR ? ToPPR(DestReg) : DestReg.asMCReg();
6021
6022 if (PPRSrcReg != PPRDestReg) {
6023 auto NewMI = BuildMI(MBB, I, DL, get(AArch64::ORR_PPzPP), PPRDestReg)
6024 .addReg(PPRSrcReg) // Pg
6025 .addReg(PPRSrcReg)
6026 .addReg(PPRSrcReg, getKillRegState(KillSrc));
6027 if (DestIsPNR)
6028 NewMI.addDef(DestReg, RegState::Implicit);
6029 }
6030 return;
6031 }
6032
6033 // Copy a predicate register pair by copying the individual sub-registers.
6034 if (AArch64::PPR2RegClass.contains(DestReg) &&
6035 AArch64::PPR2RegClass.contains(SrcReg)) {
6036 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6037 "Unexpected SVE predicate register.");
6038 static const unsigned Indices[] = {AArch64::psub0, AArch64::psub1};
6039 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6040 return;
6041 }
6042
6043 // Copy a Z register by ORRing with itself.
6044 if (AArch64::ZPRRegClass.contains(DestReg) &&
6045 AArch64::ZPRRegClass.contains(SrcReg)) {
6046 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6047 "Unexpected SVE register.");
6048 BuildMI(MBB, I, DL, get(AArch64::ORR_ZZZ), DestReg)
6049 .addReg(SrcReg)
6050 .addReg(SrcReg, getKillRegState(KillSrc));
6051 return;
6052 }
6053
6054 // Copy a Z register pair by copying the individual sub-registers.
6055 if ((AArch64::ZPR2RegClass.contains(DestReg) ||
6056 AArch64::ZPR2StridedOrContiguousRegClass.contains(DestReg)) &&
6057 (AArch64::ZPR2RegClass.contains(SrcReg) ||
6058 AArch64::ZPR2StridedOrContiguousRegClass.contains(SrcReg))) {
6059 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6060 "Unexpected SVE register.");
6061 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1};
6062 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6063 return;
6064 }
6065
6066 // Copy a Z register triple by copying the individual sub-registers.
6067 if (AArch64::ZPR3RegClass.contains(DestReg) &&
6068 AArch64::ZPR3RegClass.contains(SrcReg)) {
6069 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6070 "Unexpected SVE register.");
6071 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
6072 AArch64::zsub2};
6073 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6074 return;
6075 }
6076
6077 // Copy a Z register quad by copying the individual sub-registers.
6078 if ((AArch64::ZPR4RegClass.contains(DestReg) ||
6079 AArch64::ZPR4StridedOrContiguousRegClass.contains(DestReg)) &&
6080 (AArch64::ZPR4RegClass.contains(SrcReg) ||
6081 AArch64::ZPR4StridedOrContiguousRegClass.contains(SrcReg))) {
6082 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6083 "Unexpected SVE register.");
6084 static const unsigned Indices[] = {AArch64::zsub0, AArch64::zsub1,
6085 AArch64::zsub2, AArch64::zsub3};
6086 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6087 return;
6088 }
6089
6090 // Copy a DDDD register quad by copying the individual sub-registers.
6091 if (AArch64::DDDDRegClass.contains(DestReg) &&
6092 AArch64::DDDDRegClass.contains(SrcReg)) {
6093 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
6094 AArch64::dsub2, AArch64::dsub3};
6095 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6096 return;
6097 }
6098
6099 // Copy a DDD register triple by copying the individual sub-registers.
6100 if (AArch64::DDDRegClass.contains(DestReg) &&
6101 AArch64::DDDRegClass.contains(SrcReg)) {
6102 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1,
6103 AArch64::dsub2};
6104 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6105 return;
6106 }
6107
6108 // Copy a DD register pair by copying the individual sub-registers.
6109 if (AArch64::DDRegClass.contains(DestReg) &&
6110 AArch64::DDRegClass.contains(SrcReg)) {
6111 static const unsigned Indices[] = {AArch64::dsub0, AArch64::dsub1};
6112 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6113 return;
6114 }
6115
6116 // Copy a QQQQ register quad by copying the individual sub-registers.
6117 if (AArch64::QQQQRegClass.contains(DestReg) &&
6118 AArch64::QQQQRegClass.contains(SrcReg)) {
6119 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
6120 AArch64::qsub2, AArch64::qsub3};
6121 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6122 return;
6123 }
6124
6125 // Copy a QQQ register triple by copying the individual sub-registers.
6126 if (AArch64::QQQRegClass.contains(DestReg) &&
6127 AArch64::QQQRegClass.contains(SrcReg)) {
6128 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1,
6129 AArch64::qsub2};
6130 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6131 return;
6132 }
6133
6134 // Copy a QQ register pair by copying the individual sub-registers.
6135 if (AArch64::QQRegClass.contains(DestReg) &&
6136 AArch64::QQRegClass.contains(SrcReg)) {
6137 static const unsigned Indices[] = {AArch64::qsub0, AArch64::qsub1};
6138 copyPhysRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, Indices);
6139 return;
6140 }
6141
6142 if (AArch64::XSeqPairsClassRegClass.contains(DestReg) &&
6143 AArch64::XSeqPairsClassRegClass.contains(SrcReg)) {
6144 static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64};
6145 copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRXrs,
6146 AArch64::XZR, Indices);
6147 return;
6148 }
6149
6150 if (AArch64::WSeqPairsClassRegClass.contains(DestReg) &&
6151 AArch64::WSeqPairsClassRegClass.contains(SrcReg)) {
6152 static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32};
6153 copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRWrs,
6154 AArch64::WZR, Indices);
6155 return;
6156 }
6157
6158 if (AArch64::FPR128RegClass.contains(DestReg) &&
6159 AArch64::FPR128RegClass.contains(SrcReg)) {
6160 // In streaming regions, NEON is illegal but streaming-SVE is available.
6161 // Use SVE for copies if we're in a streaming region and SME is available.
6162 // With +sme-fa64, NEON is legal in streaming mode so we can use it.
6163 if ((Subtarget.isSVEorStreamingSVEAvailable() &&
6164 !Subtarget.isNeonAvailable()) ||
6165 mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6166 BuildMI(MBB, I, DL, get(AArch64::ORR_ZZZ))
6167 .addReg(AArch64::Z0 + (DestReg - AArch64::Q0), RegState::Define)
6168 .addReg(AArch64::Z0 + (SrcReg - AArch64::Q0))
6169 .addReg(AArch64::Z0 + (SrcReg - AArch64::Q0));
6170 } else if (Subtarget.isNeonAvailable()) {
6171 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestReg)
6172 .addReg(SrcReg)
6173 .addReg(SrcReg, getKillRegState(KillSrc));
6174 if (Subtarget.hasZeroCycleRegMoveFPR128())
6175 ++NumZCRegMoveInstrsFPR;
6176 } else {
6177 BuildMI(MBB, I, DL, get(AArch64::STRQpre))
6178 .addReg(AArch64::SP, RegState::Define)
6179 .addReg(SrcReg, getKillRegState(KillSrc))
6180 .addReg(AArch64::SP)
6181 .addImm(-16);
6182 BuildMI(MBB, I, DL, get(AArch64::LDRQpost))
6183 .addReg(AArch64::SP, RegState::Define)
6184 .addReg(DestReg, RegState::Define)
6185 .addReg(AArch64::SP)
6186 .addImm(16);
6187 }
6188 return;
6189 }
6190
6191 if (AArch64::FPR64RegClass.contains(DestReg) &&
6192 AArch64::FPR64RegClass.contains(SrcReg)) {
6193 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6194 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6195 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6196 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6197 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::dsub,
6198 &AArch64::FPR128RegClass);
6199 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::dsub,
6200 &AArch64::FPR128RegClass);
6201 // This instruction is reading and writing Q registers. This may upset
6202 // the register scavenger and machine verifier, so we need to indicate
6203 // that we are reading an undefined value from SrcRegQ, but a proper
6204 // value from SrcReg.
6205 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6206 .addReg(SrcRegQ, RegState::Undef)
6207 .addReg(SrcRegQ, RegState::Undef)
6208 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6209 ++NumZCRegMoveInstrsFPR;
6210 } else {
6211 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestReg)
6212 .addReg(SrcReg, getKillRegState(KillSrc));
6213 if (Subtarget.hasZeroCycleRegMoveFPR64())
6214 ++NumZCRegMoveInstrsFPR;
6215 }
6216 return;
6217 }
6218
6219 if (AArch64::FPR32RegClass.contains(DestReg) &&
6220 AArch64::FPR32RegClass.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::ssub,
6226 &AArch64::FPR128RegClass);
6227 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
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 if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6239 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6240 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::ssub,
6241 &AArch64::FPR64RegClass);
6242 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::ssub,
6243 &AArch64::FPR64RegClass);
6244 // This instruction is reading and writing D registers. This may upset
6245 // the register scavenger and machine verifier, so we need to indicate
6246 // that we are reading an undefined value from SrcRegD, but a proper
6247 // value from SrcReg.
6248 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6249 .addReg(SrcRegD, RegState::Undef)
6250 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6251 ++NumZCRegMoveInstrsFPR;
6252 } else {
6253 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6254 .addReg(SrcReg, getKillRegState(KillSrc));
6255 if (Subtarget.hasZeroCycleRegMoveFPR32())
6256 ++NumZCRegMoveInstrsFPR;
6257 }
6258 return;
6259 }
6260
6261 if (AArch64::FPR16RegClass.contains(DestReg) &&
6262 AArch64::FPR16RegClass.contains(SrcReg)) {
6263 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6264 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6265 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6266 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6267 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6268 &AArch64::FPR128RegClass);
6269 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6270 &AArch64::FPR128RegClass);
6271 // This instruction is reading and writing Q registers. This may upset
6272 // the register scavenger and machine verifier, so we need to indicate
6273 // that we are reading an undefined value from SrcRegQ, but a proper
6274 // value from SrcReg.
6275 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6276 .addReg(SrcRegQ, RegState::Undef)
6277 .addReg(SrcRegQ, RegState::Undef)
6278 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6279 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6280 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6281 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6282 &AArch64::FPR64RegClass);
6283 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6284 &AArch64::FPR64RegClass);
6285 // This instruction is reading and writing D registers. This may upset
6286 // the register scavenger and machine verifier, so we need to indicate
6287 // that we are reading an undefined value from SrcRegD, but a proper
6288 // value from SrcReg.
6289 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6290 .addReg(SrcRegD, RegState::Undef)
6291 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6292 } else {
6293 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::hsub,
6294 &AArch64::FPR32RegClass);
6295 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::hsub,
6296 &AArch64::FPR32RegClass);
6297 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6298 .addReg(SrcReg, getKillRegState(KillSrc));
6299 }
6300 return;
6301 }
6302
6303 if (AArch64::FPR8RegClass.contains(DestReg) &&
6304 AArch64::FPR8RegClass.contains(SrcReg)) {
6305 if (Subtarget.hasZeroCycleRegMoveFPR128() &&
6306 !Subtarget.hasZeroCycleRegMoveFPR64() &&
6307 !Subtarget.hasZeroCycleRegMoveFPR32() && Subtarget.isNeonAvailable() &&
6308 !mustAvoidNeonAtMBBI(Subtarget, MBB, I)) {
6309 MCRegister DestRegQ = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6310 &AArch64::FPR128RegClass);
6311 MCRegister SrcRegQ = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6312 &AArch64::FPR128RegClass);
6313 // This instruction is reading and writing Q 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 SrcRegQ, but a proper
6316 // value from SrcReg.
6317 BuildMI(MBB, I, DL, get(AArch64::ORRv16i8), DestRegQ)
6318 .addReg(SrcRegQ, RegState::Undef)
6319 .addReg(SrcRegQ, RegState::Undef)
6320 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6321 } else if (Subtarget.hasZeroCycleRegMoveFPR64() &&
6322 !Subtarget.hasZeroCycleRegMoveFPR32()) {
6323 MCRegister DestRegD = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6324 &AArch64::FPR64RegClass);
6325 MCRegister SrcRegD = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6326 &AArch64::FPR64RegClass);
6327 // This instruction is reading and writing D registers. This may upset
6328 // the register scavenger and machine verifier, so we need to indicate
6329 // that we are reading an undefined value from SrcRegD, but a proper
6330 // value from SrcReg.
6331 BuildMI(MBB, I, DL, get(AArch64::FMOVDr), DestRegD)
6332 .addReg(SrcRegD, RegState::Undef)
6333 .addReg(SrcReg, RegState::Implicit | getKillRegState(KillSrc));
6334 } else {
6335 DestReg = RI.getMatchingSuperReg(DestReg, AArch64::bsub,
6336 &AArch64::FPR32RegClass);
6337 SrcReg = RI.getMatchingSuperReg(SrcReg, AArch64::bsub,
6338 &AArch64::FPR32RegClass);
6339 BuildMI(MBB, I, DL, get(AArch64::FMOVSr), DestReg)
6340 .addReg(SrcReg, getKillRegState(KillSrc));
6341 }
6342 return;
6343 }
6344
6345 // Copies between GPR64 and FPR64.
6346 if (AArch64::FPR64RegClass.contains(DestReg) &&
6347 AArch64::GPR64RegClass.contains(SrcReg)) {
6348 if (AArch64::XZR == SrcReg) {
6349 BuildMI(MBB, I, DL, get(AArch64::FMOVD0), DestReg);
6350 } else {
6351 BuildMI(MBB, I, DL, get(AArch64::FMOVXDr), DestReg)
6352 .addReg(SrcReg, getKillRegState(KillSrc));
6353 }
6354 return;
6355 }
6356 if (AArch64::GPR64RegClass.contains(DestReg) &&
6357 AArch64::FPR64RegClass.contains(SrcReg)) {
6358 BuildMI(MBB, I, DL, get(AArch64::FMOVDXr), DestReg)
6359 .addReg(SrcReg, getKillRegState(KillSrc));
6360 return;
6361 }
6362 // Copies between GPR32 and FPR32.
6363 if (AArch64::FPR32RegClass.contains(DestReg) &&
6364 AArch64::GPR32RegClass.contains(SrcReg)) {
6365 if (AArch64::WZR == SrcReg) {
6366 BuildMI(MBB, I, DL, get(AArch64::FMOVS0), DestReg);
6367 } else {
6368 BuildMI(MBB, I, DL, get(AArch64::FMOVWSr), DestReg)
6369 .addReg(SrcReg, getKillRegState(KillSrc));
6370 }
6371 return;
6372 }
6373 if (AArch64::GPR32RegClass.contains(DestReg) &&
6374 AArch64::FPR32RegClass.contains(SrcReg)) {
6375 BuildMI(MBB, I, DL, get(AArch64::FMOVSWr), DestReg)
6376 .addReg(SrcReg, getKillRegState(KillSrc));
6377 return;
6378 }
6379
6380 if (DestReg == AArch64::NZCV) {
6381 assert(AArch64::GPR64RegClass.contains(SrcReg) && "Invalid NZCV copy");
6382 BuildMI(MBB, I, DL, get(AArch64::MSR))
6383 .addImm(AArch64SysReg::NZCV)
6384 .addReg(SrcReg, getKillRegState(KillSrc))
6385 .addReg(AArch64::NZCV, RegState::Implicit | RegState::Define);
6386 return;
6387 }
6388
6389 if (SrcReg == AArch64::NZCV) {
6390 assert(AArch64::GPR64RegClass.contains(DestReg) && "Invalid NZCV copy");
6391 BuildMI(MBB, I, DL, get(AArch64::MRS), DestReg)
6392 .addImm(AArch64SysReg::NZCV)
6393 .addReg(AArch64::NZCV, RegState::Implicit | getKillRegState(KillSrc));
6394 return;
6395 }
6396
6397#ifndef NDEBUG
6398 errs() << RI.getRegAsmName(DestReg) << " = COPY " << RI.getRegAsmName(SrcReg)
6399 << "\n";
6400#endif
6401 llvm_unreachable("unimplemented reg-to-reg copy");
6402}
6403
6406 const DebugLoc &DL, Register DestReg,
6407 Register SrcReg, bool KillSrc,
6408 bool RenamableDest,
6409 bool RenamableSrc) const {
6410 ++NumCopyInstrs;
6411 copyPhysRegImpl(MBB, I, DL, DestReg, SrcReg, KillSrc, RenamableDest,
6412 RenamableSrc);
6413 return;
6414}
6415
6418 MachineBasicBlock::iterator InsertBefore,
6419 const MCInstrDesc &MCID,
6420 Register SrcReg, bool IsKill,
6421 unsigned SubIdx0, unsigned SubIdx1, int FI,
6422 MachineMemOperand *MMO) {
6423 Register SrcReg0 = SrcReg;
6424 Register SrcReg1 = SrcReg;
6425 if (SrcReg.isPhysical()) {
6426 SrcReg0 = TRI.getSubReg(SrcReg, SubIdx0);
6427 SubIdx0 = 0;
6428 SrcReg1 = TRI.getSubReg(SrcReg, SubIdx1);
6429 SubIdx1 = 0;
6430 }
6431 BuildMI(MBB, InsertBefore, DebugLoc(), MCID)
6432 .addReg(SrcReg0, getKillRegState(IsKill), SubIdx0)
6433 .addReg(SrcReg1, getKillRegState(IsKill), SubIdx1)
6434 .addFrameIndex(FI)
6435 .addImm(0)
6436 .addMemOperand(MMO);
6437}
6438
6441 Register SrcReg, bool isKill, int FI,
6442 const TargetRegisterClass *RC,
6443 Register VReg,
6444 MachineInstr::MIFlag Flags) const {
6445 MachineFunction &MF = *MBB.getParent();
6446 MachineFrameInfo &MFI = MF.getFrameInfo();
6447
6449 MachineMemOperand *MMO =
6451 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
6452 unsigned Opc = 0;
6453 bool Offset = true;
6455 unsigned StackID = TargetStackID::Default;
6456 switch (RI.getSpillSize(*RC)) {
6457 case 1:
6458 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6459 Opc = AArch64::STRBui;
6460 break;
6461 case 2: {
6462 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6463 Opc = AArch64::STRHui;
6464 else if (AArch64::PNRRegClass.hasSubClassEq(RC) ||
6465 AArch64::PPRRegClass.hasSubClassEq(RC)) {
6466 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6467 "Unexpected register store without SVE store instructions");
6468 Opc = AArch64::STR_PXI;
6470 }
6471 break;
6472 }
6473 case 4:
6474 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6475 Opc = AArch64::STRWui;
6476 if (SrcReg.isVirtual())
6477 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR32RegClass);
6478 else
6479 assert(SrcReg != AArch64::WSP);
6480 } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6481 Opc = AArch64::STRSui;
6482 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6483 Opc = AArch64::STR_PPXI;
6485 }
6486 break;
6487 case 8:
6488 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6489 Opc = AArch64::STRXui;
6490 if (SrcReg.isVirtual())
6491 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
6492 else
6493 assert(SrcReg != AArch64::SP);
6494 } else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6495 Opc = AArch64::STRDui;
6496 } else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6498 get(AArch64::STPWi), SrcReg, isKill,
6499 AArch64::sube32, AArch64::subo32, FI, MMO);
6500 return;
6501 }
6502 break;
6503 case 16:
6504 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6505 Opc = AArch64::STRQui;
6506 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6507 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6508 Opc = AArch64::ST1Twov1d;
6509 Offset = false;
6510 } else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6512 get(AArch64::STPXi), SrcReg, isKill,
6513 AArch64::sube64, AArch64::subo64, FI, MMO);
6514 return;
6515 } else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6516 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6517 "Unexpected register store without SVE store instructions");
6518 Opc = AArch64::STR_ZXI;
6520 }
6521 break;
6522 case 24:
6523 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6524 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6525 Opc = AArch64::ST1Threev1d;
6526 Offset = false;
6527 }
6528 break;
6529 case 32:
6530 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6531 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6532 Opc = AArch64::ST1Fourv1d;
6533 Offset = false;
6534 } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6535 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6536 Opc = AArch64::ST1Twov2d;
6537 Offset = false;
6538 } else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6539 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6540 "Unexpected register store without SVE store instructions");
6541 Opc = AArch64::STR_ZZXI_STRIDED_CONTIGUOUS;
6543 } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6544 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6545 "Unexpected register store without SVE store instructions");
6546 Opc = AArch64::STR_ZZXI;
6548 }
6549 break;
6550 case 48:
6551 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6552 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6553 Opc = AArch64::ST1Threev2d;
6554 Offset = false;
6555 } else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6556 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6557 "Unexpected register store without SVE store instructions");
6558 Opc = AArch64::STR_ZZZXI;
6560 }
6561 break;
6562 case 64:
6563 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6564 assert(Subtarget.hasNEON() && "Unexpected register store without NEON");
6565 Opc = AArch64::ST1Fourv2d;
6566 Offset = false;
6567 } else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6568 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6569 "Unexpected register store without SVE store instructions");
6570 Opc = AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS;
6572 } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6573 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6574 "Unexpected register store without SVE store instructions");
6575 Opc = AArch64::STR_ZZZZXI;
6577 }
6578 break;
6579 }
6580 assert(Opc && "Unknown register class");
6581 MFI.setStackID(FI, StackID);
6582
6584 .addReg(SrcReg, getKillRegState(isKill))
6585 .addFrameIndex(FI);
6586
6587 if (Offset)
6588 MI.addImm(0);
6589 if (PNRReg.isValid())
6590 MI.addDef(PNRReg, RegState::Implicit);
6591 MI.addMemOperand(MMO);
6592}
6593
6596 MachineBasicBlock::iterator InsertBefore,
6597 const MCInstrDesc &MCID,
6598 Register DestReg, unsigned SubIdx0,
6599 unsigned SubIdx1, int FI,
6600 MachineMemOperand *MMO) {
6601 Register DestReg0 = DestReg;
6602 Register DestReg1 = DestReg;
6603 bool IsUndef = true;
6604 if (DestReg.isPhysical()) {
6605 DestReg0 = TRI.getSubReg(DestReg, SubIdx0);
6606 SubIdx0 = 0;
6607 DestReg1 = TRI.getSubReg(DestReg, SubIdx1);
6608 SubIdx1 = 0;
6609 IsUndef = false;
6610 }
6611 BuildMI(MBB, InsertBefore, DebugLoc(), MCID)
6612 .addReg(DestReg0, RegState::Define | getUndefRegState(IsUndef), SubIdx0)
6613 .addReg(DestReg1, RegState::Define | getUndefRegState(IsUndef), SubIdx1)
6614 .addFrameIndex(FI)
6615 .addImm(0)
6616 .addMemOperand(MMO);
6617}
6618
6621 Register DestReg, int FI,
6622 const TargetRegisterClass *RC,
6623 Register VReg, unsigned SubReg,
6624 MachineInstr::MIFlag Flags) const {
6625 MachineFunction &MF = *MBB.getParent();
6626 MachineFrameInfo &MFI = MF.getFrameInfo();
6628 MachineMemOperand *MMO =
6630 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
6631
6632 unsigned Opc = 0;
6633 bool Offset = true;
6634 unsigned StackID = TargetStackID::Default;
6635 Register PNRReg;
6636 switch (TRI.getSpillSize(*RC)) {
6637 case 1:
6638 if (AArch64::FPR8RegClass.hasSubClassEq(RC))
6639 Opc = AArch64::LDRBui;
6640 break;
6641 case 2: {
6642 bool IsPNR = AArch64::PNRRegClass.hasSubClassEq(RC);
6643 if (AArch64::FPR16RegClass.hasSubClassEq(RC))
6644 Opc = AArch64::LDRHui;
6645 else if (IsPNR || AArch64::PPRRegClass.hasSubClassEq(RC)) {
6646 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6647 "Unexpected register load without SVE load instructions");
6648 if (IsPNR)
6649 PNRReg = DestReg;
6650 Opc = AArch64::LDR_PXI;
6652 }
6653 break;
6654 }
6655 case 4:
6656 if (AArch64::GPR32allRegClass.hasSubClassEq(RC)) {
6657 Opc = AArch64::LDRWui;
6658 if (DestReg.isVirtual())
6659 MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR32RegClass);
6660 else
6661 assert(DestReg != AArch64::WSP);
6662 } else if (AArch64::FPR32RegClass.hasSubClassEq(RC))
6663 Opc = AArch64::LDRSui;
6664 else if (AArch64::PPR2RegClass.hasSubClassEq(RC)) {
6665 Opc = AArch64::LDR_PPXI;
6667 }
6668 break;
6669 case 8:
6670 if (AArch64::GPR64allRegClass.hasSubClassEq(RC)) {
6671 Opc = AArch64::LDRXui;
6672 if (DestReg.isVirtual())
6673 MF.getRegInfo().constrainRegClass(DestReg, &AArch64::GPR64RegClass);
6674 else
6675 assert(DestReg != AArch64::SP);
6676 } else if (AArch64::FPR64RegClass.hasSubClassEq(RC)) {
6677 Opc = AArch64::LDRDui;
6678 } else if (AArch64::WSeqPairsClassRegClass.hasSubClassEq(RC)) {
6680 get(AArch64::LDPWi), DestReg, AArch64::sube32,
6681 AArch64::subo32, FI, MMO);
6682 return;
6683 }
6684 break;
6685 case 16:
6686 if (AArch64::FPR128RegClass.hasSubClassEq(RC))
6687 Opc = AArch64::LDRQui;
6688 else if (AArch64::DDRegClass.hasSubClassEq(RC)) {
6689 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6690 Opc = AArch64::LD1Twov1d;
6691 Offset = false;
6692 } else if (AArch64::XSeqPairsClassRegClass.hasSubClassEq(RC)) {
6694 get(AArch64::LDPXi), DestReg, AArch64::sube64,
6695 AArch64::subo64, FI, MMO);
6696 return;
6697 } else if (AArch64::ZPRRegClass.hasSubClassEq(RC)) {
6698 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6699 "Unexpected register load without SVE load instructions");
6700 Opc = AArch64::LDR_ZXI;
6702 }
6703 break;
6704 case 24:
6705 if (AArch64::DDDRegClass.hasSubClassEq(RC)) {
6706 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6707 Opc = AArch64::LD1Threev1d;
6708 Offset = false;
6709 }
6710 break;
6711 case 32:
6712 if (AArch64::DDDDRegClass.hasSubClassEq(RC)) {
6713 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6714 Opc = AArch64::LD1Fourv1d;
6715 Offset = false;
6716 } else if (AArch64::QQRegClass.hasSubClassEq(RC)) {
6717 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6718 Opc = AArch64::LD1Twov2d;
6719 Offset = false;
6720 } else if (AArch64::ZPR2StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6721 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6722 "Unexpected register load without SVE load instructions");
6723 Opc = AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS;
6725 } else if (AArch64::ZPR2RegClass.hasSubClassEq(RC)) {
6726 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6727 "Unexpected register load without SVE load instructions");
6728 Opc = AArch64::LDR_ZZXI;
6730 }
6731 break;
6732 case 48:
6733 if (AArch64::QQQRegClass.hasSubClassEq(RC)) {
6734 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6735 Opc = AArch64::LD1Threev2d;
6736 Offset = false;
6737 } else if (AArch64::ZPR3RegClass.hasSubClassEq(RC)) {
6738 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6739 "Unexpected register load without SVE load instructions");
6740 Opc = AArch64::LDR_ZZZXI;
6742 }
6743 break;
6744 case 64:
6745 if (AArch64::QQQQRegClass.hasSubClassEq(RC)) {
6746 assert(Subtarget.hasNEON() && "Unexpected register load without NEON");
6747 Opc = AArch64::LD1Fourv2d;
6748 Offset = false;
6749 } else if (AArch64::ZPR4StridedOrContiguousRegClass.hasSubClassEq(RC)) {
6750 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6751 "Unexpected register load without SVE load instructions");
6752 Opc = AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS;
6754 } else if (AArch64::ZPR4RegClass.hasSubClassEq(RC)) {
6755 assert(Subtarget.isSVEorStreamingSVEAvailable() &&
6756 "Unexpected register load without SVE load instructions");
6757 Opc = AArch64::LDR_ZZZZXI;
6759 }
6760 break;
6761 }
6762
6763 assert(Opc && "Unknown register class");
6764 MFI.setStackID(FI, StackID);
6765
6767 .addReg(DestReg, getDefRegState(true))
6768 .addFrameIndex(FI);
6769 if (Offset)
6770 MI.addImm(0);
6771 if (PNRReg.isValid() && !PNRReg.isVirtual())
6772 MI.addDef(PNRReg, RegState::Implicit);
6773 MI.addMemOperand(MMO);
6774}
6775
6777 const MachineInstr &UseMI,
6778 const TargetRegisterInfo *TRI) {
6779 return any_of(instructionsWithoutDebug(std::next(DefMI.getIterator()),
6780 UseMI.getIterator()),
6781 [TRI](const MachineInstr &I) {
6782 return I.modifiesRegister(AArch64::NZCV, TRI) ||
6783 I.readsRegister(AArch64::NZCV, TRI);
6784 });
6785}
6786
6787void AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6788 const StackOffset &Offset, int64_t &ByteSized, int64_t &VGSized) {
6789 // The smallest scalable element supported by scaled SVE addressing
6790 // modes are predicates, which are 2 scalable bytes in size. So the scalable
6791 // byte offset must always be a multiple of 2.
6792 assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
6793
6794 // VGSized offsets are divided by '2', because the VG register is the
6795 // the number of 64bit granules as opposed to 128bit vector chunks,
6796 // which is how the 'n' in e.g. MVT::nxv1i8 is modelled.
6797 // So, for a stack offset of 16 MVT::nxv1i8's, the size is n x 16 bytes.
6798 // VG = n * 2 and the dwarf offset must be VG * 8 bytes.
6799 ByteSized = Offset.getFixed();
6800 VGSized = Offset.getScalable() / 2;
6801}
6802
6803/// Returns the offset in parts to which this frame offset can be
6804/// decomposed for the purpose of describing a frame offset.
6805/// For non-scalable offsets this is simply its byte size.
6806void AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
6807 const StackOffset &Offset, int64_t &NumBytes, int64_t &NumPredicateVectors,
6808 int64_t &NumDataVectors) {
6809 // The smallest scalable element supported by scaled SVE addressing
6810 // modes are predicates, which are 2 scalable bytes in size. So the scalable
6811 // byte offset must always be a multiple of 2.
6812 assert(Offset.getScalable() % 2 == 0 && "Invalid frame offset");
6813
6814 NumBytes = Offset.getFixed();
6815 NumDataVectors = 0;
6816 NumPredicateVectors = Offset.getScalable() / 2;
6817 // This method is used to get the offsets to adjust the frame offset.
6818 // If the function requires ADDPL to be used and needs more than two ADDPL
6819 // instructions, part of the offset is folded into NumDataVectors so that it
6820 // uses ADDVL for part of it, reducing the number of ADDPL instructions.
6821 if (NumPredicateVectors % 8 == 0 || NumPredicateVectors < -64 ||
6822 NumPredicateVectors > 62) {
6823 NumDataVectors = NumPredicateVectors / 8;
6824 NumPredicateVectors -= NumDataVectors * 8;
6825 }
6826}
6827
6828// Convenience function to create a DWARF expression for: Constant `Operation`.
6829// This helper emits compact sequences for common cases. For example, for`-15
6830// DW_OP_plus`, this helper would create DW_OP_lit15 DW_OP_minus.
6833 if (Operation == dwarf::DW_OP_plus && Constant < 0 && -Constant <= 31) {
6834 // -Constant (1 to 31)
6835 Expr.push_back(dwarf::DW_OP_lit0 - Constant);
6836 Operation = dwarf::DW_OP_minus;
6837 } else if (Constant >= 0 && Constant <= 31) {
6838 // Literal value 0 to 31
6839 Expr.push_back(dwarf::DW_OP_lit0 + Constant);
6840 } else {
6841 // Signed constant
6842 Expr.push_back(dwarf::DW_OP_consts);
6844 }
6845 return Expr.push_back(Operation);
6846}
6847
6848// Convenience function to create a DWARF expression for a register.
6849static void appendReadRegExpr(SmallVectorImpl<char> &Expr, unsigned RegNum) {
6850 Expr.push_back((char)dwarf::DW_OP_bregx);
6852 Expr.push_back(0);
6853}
6854
6855// Convenience function to create a DWARF expression for loading a register from
6856// a CFA offset.
6858 int64_t OffsetFromDefCFA) {
6859 // This assumes the top of the DWARF stack contains the CFA.
6860 Expr.push_back(dwarf::DW_OP_dup);
6861 // Add the offset to the register.
6862 appendConstantExpr(Expr, OffsetFromDefCFA, dwarf::DW_OP_plus);
6863 // Dereference the address (loads a 64 bit value)..
6864 Expr.push_back(dwarf::DW_OP_deref);
6865}
6866
6867// Convenience function to create a comment for
6868// (+/-) NumBytes (* RegScale)?
6869static void appendOffsetComment(int NumBytes, llvm::raw_string_ostream &Comment,
6870 StringRef RegScale = {}) {
6871 if (NumBytes) {
6872 Comment << (NumBytes < 0 ? " - " : " + ") << std::abs(NumBytes);
6873 if (!RegScale.empty())
6874 Comment << ' ' << RegScale;
6875 }
6876}
6877
6878// Creates an MCCFIInstruction:
6879// { DW_CFA_def_cfa_expression, ULEB128 (sizeof expr), expr }
6881 unsigned Reg,
6882 const StackOffset &Offset) {
6883 int64_t NumBytes, NumVGScaledBytes;
6884 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(Offset, NumBytes,
6885 NumVGScaledBytes);
6886 std::string CommentBuffer;
6887 llvm::raw_string_ostream Comment(CommentBuffer);
6888
6889 if (Reg == AArch64::SP)
6890 Comment << "sp";
6891 else if (Reg == AArch64::FP)
6892 Comment << "fp";
6893 else
6894 Comment << printReg(Reg, &TRI);
6895
6896 // Build up the expression (Reg + NumBytes + VG * NumVGScaledBytes)
6897 SmallString<64> Expr;
6898 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6899 assert(DwarfReg <= 31 && "DwarfReg out of bounds (0..31)");
6900 // Reg + NumBytes
6901 Expr.push_back(dwarf::DW_OP_breg0 + DwarfReg);
6902 appendLEB128<LEB128Sign::Signed>(Expr, NumBytes);
6903 appendOffsetComment(NumBytes, Comment);
6904 if (NumVGScaledBytes) {
6905 // + VG * NumVGScaledBytes
6906 appendOffsetComment(NumVGScaledBytes, Comment, "* VG");
6907 appendReadRegExpr(Expr, TRI.getDwarfRegNum(AArch64::VG, true));
6908 appendConstantExpr(Expr, NumVGScaledBytes, dwarf::DW_OP_mul);
6909 Expr.push_back(dwarf::DW_OP_plus);
6910 }
6911
6912 // Wrap this into DW_CFA_def_cfa.
6913 SmallString<64> DefCfaExpr;
6914 DefCfaExpr.push_back(dwarf::DW_CFA_def_cfa_expression);
6915 appendLEB128<LEB128Sign::Unsigned>(DefCfaExpr, Expr.size());
6916 DefCfaExpr.append(Expr.str());
6917 return MCCFIInstruction::createEscape(nullptr, DefCfaExpr.str(), SMLoc(),
6918 Comment.str());
6919}
6920
6922 unsigned FrameReg, unsigned Reg,
6923 const StackOffset &Offset,
6924 bool LastAdjustmentWasScalable) {
6925 if (Offset.getScalable())
6926 return createDefCFAExpression(TRI, Reg, Offset);
6927
6928 if (FrameReg == Reg && !LastAdjustmentWasScalable)
6929 return MCCFIInstruction::cfiDefCfaOffset(nullptr, int(Offset.getFixed()));
6930
6931 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6932 return MCCFIInstruction::cfiDefCfa(nullptr, DwarfReg, (int)Offset.getFixed());
6933}
6934
6937 const StackOffset &OffsetFromDefCFA,
6938 std::optional<int64_t> IncomingVGOffsetFromDefCFA) {
6939 int64_t NumBytes, NumVGScaledBytes;
6940 AArch64InstrInfo::decomposeStackOffsetForDwarfOffsets(
6941 OffsetFromDefCFA, NumBytes, NumVGScaledBytes);
6942
6943 unsigned DwarfReg = TRI.getDwarfRegNum(Reg, true);
6944
6945 // Non-scalable offsets can use DW_CFA_offset directly.
6946 if (!NumVGScaledBytes)
6947 return MCCFIInstruction::createOffset(nullptr, DwarfReg, NumBytes);
6948
6949 std::string CommentBuffer;
6950 llvm::raw_string_ostream Comment(CommentBuffer);
6951 Comment << printReg(Reg, &TRI) << " @ cfa";
6952
6953 // Build up expression (CFA + VG * NumVGScaledBytes + NumBytes)
6954 assert(NumVGScaledBytes && "Expected scalable offset");
6955 SmallString<64> OffsetExpr;
6956 // + VG * NumVGScaledBytes
6957 StringRef VGRegScale;
6958 if (IncomingVGOffsetFromDefCFA) {
6959 appendLoadRegExpr(OffsetExpr, *IncomingVGOffsetFromDefCFA);
6960 VGRegScale = "* IncomingVG";
6961 } else {
6962 appendReadRegExpr(OffsetExpr, TRI.getDwarfRegNum(AArch64::VG, true));
6963 VGRegScale = "* VG";
6964 }
6965 appendConstantExpr(OffsetExpr, NumVGScaledBytes, dwarf::DW_OP_mul);
6966 appendOffsetComment(NumVGScaledBytes, Comment, VGRegScale);
6967 OffsetExpr.push_back(dwarf::DW_OP_plus);
6968 if (NumBytes) {
6969 // + NumBytes
6970 appendOffsetComment(NumBytes, Comment);
6971 appendConstantExpr(OffsetExpr, NumBytes, dwarf::DW_OP_plus);
6972 }
6973
6974 // Wrap this into DW_CFA_expression
6975 SmallString<64> CfaExpr;
6976 CfaExpr.push_back(dwarf::DW_CFA_expression);
6977 appendLEB128<LEB128Sign::Unsigned>(CfaExpr, DwarfReg);
6978 appendLEB128<LEB128Sign::Unsigned>(CfaExpr, OffsetExpr.size());
6979 CfaExpr.append(OffsetExpr.str());
6980
6981 return MCCFIInstruction::createEscape(nullptr, CfaExpr.str(), SMLoc(),
6982 Comment.str());
6983}
6984
6985// Helper function to emit a frame offset adjustment from a given
6986// pointer (SrcReg), stored into DestReg. This function is explicit
6987// in that it requires the opcode.
6990 const DebugLoc &DL, unsigned DestReg,
6991 unsigned SrcReg, int64_t Offset, unsigned Opc,
6992 const TargetInstrInfo *TII,
6993 MachineInstr::MIFlag Flag, bool NeedsWinCFI,
6994 bool *HasWinCFI, bool EmitCFAOffset,
6995 StackOffset CFAOffset, unsigned FrameReg) {
6996 int Sign = 1;
6997 unsigned MaxEncoding, ShiftSize;
6998 switch (Opc) {
6999 case AArch64::ADDXri:
7000 case AArch64::ADDSXri:
7001 case AArch64::SUBXri:
7002 case AArch64::SUBSXri:
7003 MaxEncoding = 0xfff;
7004 ShiftSize = 12;
7005 break;
7006 case AArch64::ADDVL_XXI:
7007 case AArch64::ADDPL_XXI:
7008 case AArch64::ADDSVL_XXI:
7009 case AArch64::ADDSPL_XXI:
7010 MaxEncoding = 31;
7011 ShiftSize = 0;
7012 if (Offset < 0) {
7013 MaxEncoding = 32;
7014 Sign = -1;
7015 Offset = -Offset;
7016 }
7017 break;
7018 default:
7019 llvm_unreachable("Unsupported opcode");
7020 }
7021
7022 // `Offset` can be in bytes or in "scalable bytes".
7023 int VScale = 1;
7024 if (Opc == AArch64::ADDVL_XXI || Opc == AArch64::ADDSVL_XXI)
7025 VScale = 16;
7026 else if (Opc == AArch64::ADDPL_XXI || Opc == AArch64::ADDSPL_XXI)
7027 VScale = 2;
7028
7029 // FIXME: If the offset won't fit in 24-bits, compute the offset into a
7030 // scratch register. If DestReg is a virtual register, use it as the
7031 // scratch register; otherwise, create a new virtual register (to be
7032 // replaced by the scavenger at the end of PEI). That case can be optimized
7033 // slightly if DestReg is SP which is always 16-byte aligned, so the scratch
7034 // register can be loaded with offset%8 and the add/sub can use an extending
7035 // instruction with LSL#3.
7036 // Currently the function handles any offsets but generates a poor sequence
7037 // of code.
7038 // assert(Offset < (1 << 24) && "unimplemented reg plus immediate");
7039
7040 const unsigned MaxEncodableValue = MaxEncoding << ShiftSize;
7041 Register TmpReg = DestReg;
7042 if (TmpReg == AArch64::XZR)
7043 TmpReg = MBB.getParent()->getRegInfo().createVirtualRegister(
7044 &AArch64::GPR64RegClass);
7045 do {
7046 uint64_t ThisVal = std::min<uint64_t>(Offset, MaxEncodableValue);
7047 unsigned LocalShiftSize = 0;
7048 if (ThisVal > MaxEncoding) {
7049 ThisVal = ThisVal >> ShiftSize;
7050 LocalShiftSize = ShiftSize;
7051 }
7052 assert((ThisVal >> ShiftSize) <= MaxEncoding &&
7053 "Encoding cannot handle value that big");
7054
7055 Offset -= ThisVal << LocalShiftSize;
7056 if (Offset == 0)
7057 TmpReg = DestReg;
7058 auto MBI = BuildMI(MBB, MBBI, DL, TII->get(Opc), TmpReg)
7059 .addReg(SrcReg)
7060 .addImm(Sign * (int)ThisVal);
7061 if (ShiftSize)
7062 MBI = MBI.addImm(
7064 MBI = MBI.setMIFlag(Flag);
7065
7066 auto Change =
7067 VScale == 1
7068 ? StackOffset::getFixed(ThisVal << LocalShiftSize)
7069 : StackOffset::getScalable(VScale * (ThisVal << LocalShiftSize));
7070 if (Sign == -1 || Opc == AArch64::SUBXri || Opc == AArch64::SUBSXri)
7071 CFAOffset += Change;
7072 else
7073 CFAOffset -= Change;
7074 if (EmitCFAOffset && DestReg == TmpReg) {
7075 MachineFunction &MF = *MBB.getParent();
7076 const TargetSubtargetInfo &STI = MF.getSubtarget();
7077 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
7078
7079 unsigned CFIIndex = MF.addFrameInst(
7080 createDefCFA(TRI, FrameReg, DestReg, CFAOffset, VScale != 1));
7081 BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION))
7082 .addCFIIndex(CFIIndex)
7083 .setMIFlags(Flag);
7084 }
7085
7086 if (NeedsWinCFI) {
7087 int Imm = (int)(ThisVal << LocalShiftSize);
7088 if (VScale != 1 && DestReg == AArch64::SP) {
7089 if (HasWinCFI)
7090 *HasWinCFI = true;
7091 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AllocZ))
7092 .addImm(ThisVal)
7093 .setMIFlag(Flag);
7094 } else if ((DestReg == AArch64::FP && SrcReg == AArch64::SP) ||
7095 (SrcReg == AArch64::FP && DestReg == AArch64::SP)) {
7096 assert(VScale == 1 && "Expected non-scalable operation");
7097 if (HasWinCFI)
7098 *HasWinCFI = true;
7099 if (Imm == 0)
7100 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_SetFP)).setMIFlag(Flag);
7101 else
7102 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_AddFP))
7103 .addImm(Imm)
7104 .setMIFlag(Flag);
7105 assert(Offset == 0 && "Expected remaining offset to be zero to "
7106 "emit a single SEH directive");
7107 } else if (DestReg == AArch64::SP) {
7108 assert(VScale == 1 && "Expected non-scalable operation");
7109 if (HasWinCFI)
7110 *HasWinCFI = true;
7111 assert(SrcReg == AArch64::SP && "Unexpected SrcReg for SEH_StackAlloc");
7112 BuildMI(MBB, MBBI, DL, TII->get(AArch64::SEH_StackAlloc))
7113 .addImm(Imm)
7114 .setMIFlag(Flag);
7115 }
7116 }
7117
7118 SrcReg = TmpReg;
7119 } while (Offset);
7120}
7121
7124 unsigned DestReg, unsigned SrcReg,
7126 MachineInstr::MIFlag Flag, bool SetNZCV,
7127 bool NeedsWinCFI, bool *HasWinCFI,
7128 bool EmitCFAOffset, StackOffset CFAOffset,
7129 unsigned FrameReg) {
7130 // If a function is marked as arm_locally_streaming, then the runtime value of
7131 // vscale in the prologue/epilogue is different the runtime value of vscale
7132 // in the function's body. To avoid having to consider multiple vscales,
7133 // we can use `addsvl` to allocate any scalable stack-slots, which under
7134 // most circumstances will be only locals, not callee-save slots.
7135 const Function &F = MBB.getParent()->getFunction();
7136 bool UseSVL = F.hasFnAttribute("aarch64_pstate_sm_body");
7137
7138 int64_t Bytes, NumPredicateVectors, NumDataVectors;
7139 AArch64InstrInfo::decomposeStackOffsetForFrameOffsets(
7140 Offset, Bytes, NumPredicateVectors, NumDataVectors);
7141
7142 // Insert ADDSXri for scalable offset at the end.
7143 bool NeedsFinalDefNZCV = SetNZCV && (NumPredicateVectors || NumDataVectors);
7144 if (NeedsFinalDefNZCV)
7145 SetNZCV = false;
7146
7147 // First emit non-scalable frame offsets, or a simple 'mov'.
7148 if (Bytes || (!Offset && SrcReg != DestReg)) {
7149 assert((DestReg != AArch64::SP || Bytes % 8 == 0) &&
7150 "SP increment/decrement not 8-byte aligned");
7151 unsigned Opc = SetNZCV ? AArch64::ADDSXri : AArch64::ADDXri;
7152 if (Bytes < 0) {
7153 Bytes = -Bytes;
7154 Opc = SetNZCV ? AArch64::SUBSXri : AArch64::SUBXri;
7155 }
7156 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, Bytes, Opc, TII, Flag,
7157 NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7158 FrameReg);
7159 CFAOffset += (Opc == AArch64::ADDXri || Opc == AArch64::ADDSXri)
7160 ? StackOffset::getFixed(-Bytes)
7161 : StackOffset::getFixed(Bytes);
7162 SrcReg = DestReg;
7163 FrameReg = DestReg;
7164 }
7165
7166 assert(!(NeedsWinCFI && NumPredicateVectors) &&
7167 "WinCFI can't allocate fractions of an SVE data vector");
7168
7169 if (NumDataVectors) {
7170 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, NumDataVectors,
7171 UseSVL ? AArch64::ADDSVL_XXI : AArch64::ADDVL_XXI, TII,
7172 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7173 FrameReg);
7174 CFAOffset += StackOffset::getScalable(-NumDataVectors * 16);
7175 SrcReg = DestReg;
7176 }
7177
7178 if (NumPredicateVectors) {
7179 assert(DestReg != AArch64::SP && "Unaligned access to SP");
7180 emitFrameOffsetAdj(MBB, MBBI, DL, DestReg, SrcReg, NumPredicateVectors,
7181 UseSVL ? AArch64::ADDSPL_XXI : AArch64::ADDPL_XXI, TII,
7182 Flag, NeedsWinCFI, HasWinCFI, EmitCFAOffset, CFAOffset,
7183 FrameReg);
7184 }
7185
7186 if (NeedsFinalDefNZCV)
7187 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ADDSXri), DestReg)
7188 .addReg(DestReg)
7189 .addImm(0)
7190 .addImm(0);
7191}
7192
7195 int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS,
7196 VirtRegMap *VRM) const {
7198 // This is a bit of a hack. Consider this instruction:
7199 //
7200 // %0 = COPY %sp; GPR64all:%0
7201 //
7202 // We explicitly chose GPR64all for the virtual register so such a copy might
7203 // be eliminated by RegisterCoalescer. However, that may not be possible, and
7204 // %0 may even spill. We can't spill %sp, and since it is in the GPR64all
7205 // register class, TargetInstrInfo::foldMemoryOperand() is going to try.
7206 //
7207 // To prevent that, we are going to constrain the %0 register class here.
7208 if (MI.isFullCopy()) {
7209 Register DstReg = MI.getOperand(0).getReg();
7210 Register SrcReg = MI.getOperand(1).getReg();
7211 if (SrcReg == AArch64::SP && DstReg.isVirtual()) {
7212 MF.getRegInfo().constrainRegClass(DstReg, &AArch64::GPR64RegClass);
7213 return nullptr;
7214 }
7215 if (DstReg == AArch64::SP && SrcReg.isVirtual()) {
7216 MF.getRegInfo().constrainRegClass(SrcReg, &AArch64::GPR64RegClass);
7217 return nullptr;
7218 }
7219 // Nothing can folded with copy from/to NZCV.
7220 if (SrcReg == AArch64::NZCV || DstReg == AArch64::NZCV)
7221 return nullptr;
7222 }
7223
7224 // Handle the case where a copy is being spilled or filled but the source
7225 // and destination register class don't match. For example:
7226 //
7227 // %0 = COPY %xzr; GPR64common:%0
7228 //
7229 // In this case we can still safely fold away the COPY and generate the
7230 // following spill code:
7231 //
7232 // STRXui %xzr, %stack.0
7233 //
7234 // This also eliminates spilled cross register class COPYs (e.g. between x and
7235 // d regs) of the same size. For example:
7236 //
7237 // %0 = COPY %1; GPR64:%0, FPR64:%1
7238 //
7239 // will be filled as
7240 //
7241 // LDRDui %0, fi<#0>
7242 //
7243 // instead of
7244 //
7245 // LDRXui %Temp, fi<#0>
7246 // %0 = FMOV %Temp
7247 //
7248 if (MI.isCopy() && Ops.size() == 1 &&
7249 // Make sure we're only folding the explicit COPY defs/uses.
7250 (Ops[0] == 0 || Ops[0] == 1)) {
7251 bool IsSpill = Ops[0] == 0;
7252 bool IsFill = !IsSpill;
7254 const MachineRegisterInfo &MRI = MF.getRegInfo();
7255 MachineBasicBlock &MBB = *MI.getParent();
7256 const MachineOperand &DstMO = MI.getOperand(0);
7257 const MachineOperand &SrcMO = MI.getOperand(1);
7258 Register DstReg = DstMO.getReg();
7259 Register SrcReg = SrcMO.getReg();
7260 // This is slightly expensive to compute for physical regs since
7261 // getMinimalPhysRegClass is slow.
7262 auto getRegClass = [&](unsigned Reg) {
7263 return Register::isVirtualRegister(Reg) ? MRI.getRegClass(Reg)
7264 : TRI.getMinimalPhysRegClass(Reg);
7265 };
7266
7267 if (DstMO.getSubReg() == 0 && SrcMO.getSubReg() == 0) {
7268 assert(TRI.getRegSizeInBits(*getRegClass(DstReg)) ==
7269 TRI.getRegSizeInBits(*getRegClass(SrcReg)) &&
7270 "Mismatched register size in non subreg COPY");
7271 if (IsSpill)
7272 storeRegToStackSlot(MBB, InsertPt, SrcReg, SrcMO.isKill(), FrameIndex,
7273 getRegClass(SrcReg), Register());
7274 else
7275 loadRegFromStackSlot(MBB, InsertPt, DstReg, FrameIndex,
7276 getRegClass(DstReg), Register());
7277 return &*--InsertPt;
7278 }
7279
7280 // Handle cases like spilling def of:
7281 //
7282 // %0:sub_32<def,read-undef> = COPY %wzr; GPR64common:%0
7283 //
7284 // where the physical register source can be widened and stored to the full
7285 // virtual reg destination stack slot, in this case producing:
7286 //
7287 // STRXui %xzr, %stack.0
7288 //
7289 if (IsSpill && DstMO.isUndef() && SrcReg == AArch64::WZR &&
7290 TRI.getRegSizeInBits(*getRegClass(DstReg)) == 64) {
7291 assert(SrcMO.getSubReg() == 0 &&
7292 "Unexpected subreg on physical register");
7293 storeRegToStackSlot(MBB, InsertPt, AArch64::XZR, SrcMO.isKill(),
7294 FrameIndex, &AArch64::GPR64RegClass, Register());
7295 return &*--InsertPt;
7296 }
7297
7298 // Handle cases like filling use of:
7299 //
7300 // %0:sub_32<def,read-undef> = COPY %1; GPR64:%0, GPR32:%1
7301 //
7302 // where we can load the full virtual reg source stack slot, into the subreg
7303 // destination, in this case producing:
7304 //
7305 // LDRWui %0:sub_32<def,read-undef>, %stack.0
7306 //
7307 if (IsFill && SrcMO.getSubReg() == 0 && DstMO.isUndef()) {
7308 const TargetRegisterClass *FillRC = nullptr;
7309 switch (DstMO.getSubReg()) {
7310 default:
7311 break;
7312 case AArch64::sub_32:
7313 if (AArch64::GPR64RegClass.hasSubClassEq(getRegClass(DstReg)))
7314 FillRC = &AArch64::GPR32RegClass;
7315 break;
7316 case AArch64::ssub:
7317 FillRC = &AArch64::FPR32RegClass;
7318 break;
7319 case AArch64::dsub:
7320 FillRC = &AArch64::FPR64RegClass;
7321 break;
7322 }
7323
7324 if (FillRC) {
7325 assert(TRI.getRegSizeInBits(*getRegClass(SrcReg)) ==
7326 TRI.getRegSizeInBits(*FillRC) &&
7327 "Mismatched regclass size on folded subreg COPY");
7328 loadRegFromStackSlot(MBB, InsertPt, DstReg, FrameIndex, FillRC,
7329 Register());
7330 MachineInstr &LoadMI = *--InsertPt;
7331 MachineOperand &LoadDst = LoadMI.getOperand(0);
7332 assert(LoadDst.getSubReg() == 0 && "unexpected subreg on fill load");
7333 LoadDst.setSubReg(DstMO.getSubReg());
7334 LoadDst.setIsUndef();
7335 return &LoadMI;
7336 }
7337 }
7338 }
7339
7340 // Cannot fold.
7341 return nullptr;
7342}
7343
7345 StackOffset &SOffset,
7346 bool *OutUseUnscaledOp,
7347 unsigned *OutUnscaledOp,
7348 int64_t *EmittableOffset) {
7349 // Set output values in case of early exit.
7350 if (EmittableOffset)
7351 *EmittableOffset = 0;
7352 if (OutUseUnscaledOp)
7353 *OutUseUnscaledOp = false;
7354 if (OutUnscaledOp)
7355 *OutUnscaledOp = 0;
7356
7357 // Exit early for structured vector spills/fills as they can't take an
7358 // immediate offset.
7359 switch (MI.getOpcode()) {
7360 default:
7361 break;
7362 case AArch64::LD1Rv1d:
7363 case AArch64::LD1Rv2s:
7364 case AArch64::LD1Rv2d:
7365 case AArch64::LD1Rv4h:
7366 case AArch64::LD1Rv4s:
7367 case AArch64::LD1Rv8b:
7368 case AArch64::LD1Rv8h:
7369 case AArch64::LD1Rv16b:
7370 case AArch64::LD1Twov2d:
7371 case AArch64::LD1Threev2d:
7372 case AArch64::LD1Fourv2d:
7373 case AArch64::LD1Twov1d:
7374 case AArch64::LD1Threev1d:
7375 case AArch64::LD1Fourv1d:
7376 case AArch64::ST1Twov2d:
7377 case AArch64::ST1Threev2d:
7378 case AArch64::ST1Fourv2d:
7379 case AArch64::ST1Twov1d:
7380 case AArch64::ST1Threev1d:
7381 case AArch64::ST1Fourv1d:
7382 case AArch64::ST1i8:
7383 case AArch64::ST1i16:
7384 case AArch64::ST1i32:
7385 case AArch64::ST1i64:
7386 case AArch64::IRG:
7387 case AArch64::IRGstack:
7388 case AArch64::STGloop:
7389 case AArch64::STZGloop:
7391 }
7392
7393 // Get the min/max offset and the scale.
7394 TypeSize ScaleValue(0U, false), Width(0U, false);
7395 int64_t MinOff, MaxOff;
7396 if (!AArch64InstrInfo::getMemOpInfo(MI.getOpcode(), ScaleValue, Width, MinOff,
7397 MaxOff))
7398 llvm_unreachable("unhandled opcode in isAArch64FrameOffsetLegal");
7399
7400 // Construct the complete offset.
7401 bool IsMulVL = ScaleValue.isScalable();
7402 unsigned Scale = ScaleValue.getKnownMinValue();
7403 int64_t Offset = IsMulVL ? SOffset.getScalable() : SOffset.getFixed();
7404
7405 const MachineOperand &ImmOpnd =
7406 MI.getOperand(AArch64InstrInfo::getLoadStoreImmIdx(MI.getOpcode()));
7407 Offset += ImmOpnd.getImm() * Scale;
7408
7409 // If the offset doesn't match the scale, we rewrite the instruction to
7410 // use the unscaled instruction instead. Likewise, if we have a negative
7411 // offset and there is an unscaled op to use.
7412 std::optional<unsigned> UnscaledOp =
7414 bool useUnscaledOp = UnscaledOp && (Offset % Scale || Offset < 0);
7415 if (useUnscaledOp &&
7416 !AArch64InstrInfo::getMemOpInfo(*UnscaledOp, ScaleValue, Width, MinOff,
7417 MaxOff))
7418 llvm_unreachable("unhandled opcode in isAArch64FrameOffsetLegal");
7419
7420 Scale = ScaleValue.getKnownMinValue();
7421 assert(IsMulVL == ScaleValue.isScalable() &&
7422 "Unscaled opcode has different value for scalable");
7423
7424 int64_t Remainder = Offset % Scale;
7425 assert(!(Remainder && useUnscaledOp) &&
7426 "Cannot have remainder when using unscaled op");
7427
7428 assert(MinOff < MaxOff && "Unexpected Min/Max offsets");
7429 int64_t NewOffset = Offset / Scale;
7430 if (MinOff <= NewOffset && NewOffset <= MaxOff)
7431 Offset = Remainder;
7432 else {
7433 // Try to minimise the number of instructions required to materialise the
7434 // offset calculation. Specifically, for fixed offsets, if masking out the
7435 // low 12 bits leaves a legal add immediate, we can realise the offset
7436 // calculation with a single add instruction. Whenever this is possible,
7437 // prefer this split.
7438 int64_t HighPart = Offset & ~0xFFF;
7439 int64_t LowPart = Offset & 0xFFF;
7440 int64_t LowScaled = LowPart / Scale;
7441 if (!IsMulVL && NewOffset >= 0 && LowPart % Scale == 0 &&
7442 MinOff <= LowScaled && LowScaled <= MaxOff &&
7444 NewOffset = LowScaled;
7445 Offset = HighPart;
7446 } else {
7447 // Default to a greedy split: take the memop immediate to be maximum /
7448 // minimum expressible offset and materialise the remainder.
7449 NewOffset = NewOffset < 0 ? MinOff : MaxOff;
7450 Offset = Offset - (NewOffset * Scale);
7451 }
7452 }
7453
7454 if (EmittableOffset)
7455 *EmittableOffset = NewOffset;
7456 if (OutUseUnscaledOp)
7457 *OutUseUnscaledOp = useUnscaledOp;
7458 if (OutUnscaledOp && UnscaledOp)
7459 *OutUnscaledOp = *UnscaledOp;
7460
7461 if (IsMulVL)
7462 SOffset = StackOffset::get(SOffset.getFixed(), Offset);
7463 else
7464 SOffset = StackOffset::get(Offset, SOffset.getScalable());
7466 (SOffset ? 0 : AArch64FrameOffsetIsLegal);
7467}
7468
7470 unsigned FrameReg, StackOffset &Offset,
7471 const AArch64InstrInfo *TII) {
7472 unsigned Opcode = MI.getOpcode();
7473 unsigned ImmIdx = FrameRegIdx + 1;
7474
7475 if (Opcode == AArch64::ADDSXri || Opcode == AArch64::ADDXri) {
7476 Offset += StackOffset::getFixed(MI.getOperand(ImmIdx).getImm());
7477 emitFrameOffset(*MI.getParent(), MI, MI.getDebugLoc(),
7478 MI.getOperand(0).getReg(), FrameReg, Offset, TII,
7479 MachineInstr::NoFlags, (Opcode == AArch64::ADDSXri));
7480 MI.eraseFromParent();
7481 Offset = StackOffset();
7482 return true;
7483 }
7484
7485 int64_t NewOffset;
7486 unsigned UnscaledOp;
7487 bool UseUnscaledOp;
7488 int Status = isAArch64FrameOffsetLegal(MI, Offset, &UseUnscaledOp,
7489 &UnscaledOp, &NewOffset);
7492 // Replace the FrameIndex with FrameReg.
7493 MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
7494 if (UseUnscaledOp)
7495 MI.setDesc(TII->get(UnscaledOp));
7496
7497 MI.getOperand(ImmIdx).ChangeToImmediate(NewOffset);
7498 return !Offset;
7499 }
7500
7501 return false;
7502}
7503
7509
7510MCInst AArch64InstrInfo::getNop() const { return MCInstBuilder(AArch64::NOP); }
7511
7512// AArch64 supports MachineCombiner.
7513bool AArch64InstrInfo::useMachineCombiner() const { return true; }
7514
7515// True when Opc sets flag
7516static bool isCombineInstrSettingFlag(unsigned Opc) {
7517 switch (Opc) {
7518 case AArch64::ADDSWrr:
7519 case AArch64::ADDSWri:
7520 case AArch64::ADDSXrr:
7521 case AArch64::ADDSXri:
7522 case AArch64::SUBSWrr:
7523 case AArch64::SUBSXrr:
7524 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7525 case AArch64::SUBSWri:
7526 case AArch64::SUBSXri:
7527 return true;
7528 default:
7529 break;
7530 }
7531 return false;
7532}
7533
7534// 32b Opcodes that can be combined with a MUL
7535static bool isCombineInstrCandidate32(unsigned Opc) {
7536 switch (Opc) {
7537 case AArch64::ADDWrr:
7538 case AArch64::ADDWri:
7539 case AArch64::ADDWrs:
7540 case AArch64::SUBWrr:
7541 case AArch64::ADDSWrr:
7542 case AArch64::ADDSWri:
7543 case AArch64::SUBSWrr:
7544 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7545 case AArch64::SUBWri:
7546 case AArch64::SUBSWri:
7547 return true;
7548 default:
7549 break;
7550 }
7551 return false;
7552}
7553
7554// 64b Opcodes that can be combined with a MUL
7555static bool isCombineInstrCandidate64(unsigned Opc) {
7556 switch (Opc) {
7557 case AArch64::ADDXrr:
7558 case AArch64::ADDXri:
7559 case AArch64::ADDXrs:
7560 case AArch64::SUBXrr:
7561 case AArch64::ADDSXrr:
7562 case AArch64::ADDSXri:
7563 case AArch64::SUBSXrr:
7564 // Note: MSUB Wd,Wn,Wm,Wi -> Wd = Wi - WnxWm, not Wd=WnxWm - Wi.
7565 case AArch64::SUBXri:
7566 case AArch64::SUBSXri:
7567 case AArch64::ADDv8i8:
7568 case AArch64::ADDv16i8:
7569 case AArch64::ADDv4i16:
7570 case AArch64::ADDv8i16:
7571 case AArch64::ADDv2i32:
7572 case AArch64::ADDv4i32:
7573 case AArch64::SUBv8i8:
7574 case AArch64::SUBv16i8:
7575 case AArch64::SUBv4i16:
7576 case AArch64::SUBv8i16:
7577 case AArch64::SUBv2i32:
7578 case AArch64::SUBv4i32:
7579 return true;
7580 default:
7581 break;
7582 }
7583 return false;
7584}
7585
7586// FP Opcodes that can be combined with a FMUL.
7587static bool isCombineInstrCandidateFP(const MachineInstr &Inst) {
7588 switch (Inst.getOpcode()) {
7589 default:
7590 break;
7591 case AArch64::FADDHrr:
7592 case AArch64::FADDSrr:
7593 case AArch64::FADDDrr:
7594 case AArch64::FADDv4f16:
7595 case AArch64::FADDv8f16:
7596 case AArch64::FADDv2f32:
7597 case AArch64::FADDv2f64:
7598 case AArch64::FADDv4f32:
7599 case AArch64::FSUBHrr:
7600 case AArch64::FSUBSrr:
7601 case AArch64::FSUBDrr:
7602 case AArch64::FSUBv4f16:
7603 case AArch64::FSUBv8f16:
7604 case AArch64::FSUBv2f32:
7605 case AArch64::FSUBv2f64:
7606 case AArch64::FSUBv4f32:
7607 // We can fuse FADD/FSUB with FMUL, if FADD/FSUB has the contract fast-math
7608 // flag.
7609 return Inst.getFlag(MachineInstr::FmContract);
7610 }
7611 return false;
7612}
7613
7614// Opcodes that can be combined with a MUL
7618
7619//
7620// Utility routine that checks if \param MO is defined by an
7621// \param CombineOpc instruction in the basic block \param MBB
7623 unsigned CombineOpc, unsigned ZeroReg = 0,
7624 bool CheckZeroReg = false) {
7625 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
7626 MachineInstr *MI = nullptr;
7627
7628 if (MO.isReg() && MO.getReg().isVirtual())
7629 MI = MRI.getUniqueVRegDef(MO.getReg());
7630 // And it needs to be in the trace (otherwise, it won't have a depth).
7631 if (!MI || MI->getParent() != &MBB || MI->getOpcode() != CombineOpc)
7632 return false;
7633 // Must only used by the user we combine with.
7634 if (!MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()))
7635 return false;
7636
7637 if (CheckZeroReg) {
7638 assert(MI->getNumOperands() >= 4 && MI->getOperand(0).isReg() &&
7639 MI->getOperand(1).isReg() && MI->getOperand(2).isReg() &&
7640 MI->getOperand(3).isReg() && "MAdd/MSub must have a least 4 regs");
7641 // The third input reg must be zero.
7642 if (MI->getOperand(3).getReg() != ZeroReg)
7643 return false;
7644 }
7645
7646 if (isCombineInstrSettingFlag(CombineOpc) &&
7647 MI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) == -1)
7648 return false;
7649
7650 return true;
7651}
7652
7653//
7654// Is \param MO defined by an integer multiply and can be combined?
7656 unsigned MulOpc, unsigned ZeroReg) {
7657 return canCombine(MBB, MO, MulOpc, ZeroReg, true);
7658}
7659
7660//
7661// Is \param MO defined by a floating-point multiply and can be combined?
7663 unsigned MulOpc) {
7664 return canCombine(MBB, MO, MulOpc);
7665}
7666
7667// TODO: There are many more machine instruction opcodes to match:
7668// 1. Other data types (integer, vectors)
7669// 2. Other math / logic operations (xor, or)
7670// 3. Other forms of the same operation (intrinsics and other variants)
7671bool AArch64InstrInfo::isAssociativeAndCommutative(const MachineInstr &Inst,
7672 bool Invert) const {
7673 if (Invert)
7674 return false;
7675 switch (Inst.getOpcode()) {
7676 // == Floating-point types ==
7677 // -- Floating-point instructions --
7678 case AArch64::FADDHrr:
7679 case AArch64::FADDSrr:
7680 case AArch64::FADDDrr:
7681 case AArch64::FMULHrr:
7682 case AArch64::FMULSrr:
7683 case AArch64::FMULDrr:
7684 case AArch64::FMULX16:
7685 case AArch64::FMULX32:
7686 case AArch64::FMULX64:
7687 // -- Advanced SIMD instructions --
7688 case AArch64::FADDv4f16:
7689 case AArch64::FADDv8f16:
7690 case AArch64::FADDv2f32:
7691 case AArch64::FADDv4f32:
7692 case AArch64::FADDv2f64:
7693 case AArch64::FMULv4f16:
7694 case AArch64::FMULv8f16:
7695 case AArch64::FMULv2f32:
7696 case AArch64::FMULv4f32:
7697 case AArch64::FMULv2f64:
7698 case AArch64::FMULXv4f16:
7699 case AArch64::FMULXv8f16:
7700 case AArch64::FMULXv2f32:
7701 case AArch64::FMULXv4f32:
7702 case AArch64::FMULXv2f64:
7703 // -- SVE instructions --
7704 // Opcodes FMULX_ZZZ_? don't exist because there is no unpredicated FMULX
7705 // in the SVE instruction set (though there are predicated ones).
7706 case AArch64::FADD_ZZZ_H:
7707 case AArch64::FADD_ZZZ_S:
7708 case AArch64::FADD_ZZZ_D:
7709 case AArch64::FMUL_ZZZ_H:
7710 case AArch64::FMUL_ZZZ_S:
7711 case AArch64::FMUL_ZZZ_D:
7714
7715 // == Integer types ==
7716 // -- Base instructions --
7717 // Opcodes MULWrr and MULXrr don't exist because
7718 // `MUL <Wd>, <Wn>, <Wm>` and `MUL <Xd>, <Xn>, <Xm>` are aliases of
7719 // `MADD <Wd>, <Wn>, <Wm>, WZR` and `MADD <Xd>, <Xn>, <Xm>, XZR` respectively.
7720 // The machine-combiner does not support three-source-operands machine
7721 // instruction. So we cannot reassociate MULs.
7722 case AArch64::ADDWrr:
7723 case AArch64::ADDXrr:
7724 case AArch64::ANDWrr:
7725 case AArch64::ANDXrr:
7726 case AArch64::ORRWrr:
7727 case AArch64::ORRXrr:
7728 case AArch64::EORWrr:
7729 case AArch64::EORXrr:
7730 case AArch64::EONWrr:
7731 case AArch64::EONXrr:
7732 // -- Advanced SIMD instructions --
7733 // Opcodes MULv1i64 and MULv2i64 don't exist because there is no 64-bit MUL
7734 // in the Advanced SIMD instruction set.
7735 case AArch64::ADDv8i8:
7736 case AArch64::ADDv16i8:
7737 case AArch64::ADDv4i16:
7738 case AArch64::ADDv8i16:
7739 case AArch64::ADDv2i32:
7740 case AArch64::ADDv4i32:
7741 case AArch64::ADDv1i64:
7742 case AArch64::ADDv2i64:
7743 case AArch64::MULv8i8:
7744 case AArch64::MULv16i8:
7745 case AArch64::MULv4i16:
7746 case AArch64::MULv8i16:
7747 case AArch64::MULv2i32:
7748 case AArch64::MULv4i32:
7749 case AArch64::ANDv8i8:
7750 case AArch64::ANDv16i8:
7751 case AArch64::ORRv8i8:
7752 case AArch64::ORRv16i8:
7753 case AArch64::EORv8i8:
7754 case AArch64::EORv16i8:
7755 // -- SVE instructions --
7756 case AArch64::ADD_ZZZ_B:
7757 case AArch64::ADD_ZZZ_H:
7758 case AArch64::ADD_ZZZ_S:
7759 case AArch64::ADD_ZZZ_D:
7760 case AArch64::MUL_ZZZ_B:
7761 case AArch64::MUL_ZZZ_H:
7762 case AArch64::MUL_ZZZ_S:
7763 case AArch64::MUL_ZZZ_D:
7764 case AArch64::AND_ZZZ:
7765 case AArch64::ORR_ZZZ:
7766 case AArch64::EOR_ZZZ:
7767 return true;
7768
7769 default:
7770 return false;
7771 }
7772}
7773
7774/// Find instructions that can be turned into madd.
7776 SmallVectorImpl<unsigned> &Patterns) {
7777 unsigned Opc = Root.getOpcode();
7778 MachineBasicBlock &MBB = *Root.getParent();
7779 bool Found = false;
7780
7782 return false;
7784 int Cmp_NZCV =
7785 Root.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true);
7786 // When NZCV is live bail out.
7787 if (Cmp_NZCV == -1)
7788 return false;
7789 unsigned NewOpc = convertToNonFlagSettingOpc(Root);
7790 // When opcode can't change bail out.
7791 // CHECKME: do we miss any cases for opcode conversion?
7792 if (NewOpc == Opc)
7793 return false;
7794 Opc = NewOpc;
7795 }
7796
7797 auto setFound = [&](int Opcode, int Operand, unsigned ZeroReg,
7798 unsigned Pattern) {
7799 if (canCombineWithMUL(MBB, Root.getOperand(Operand), Opcode, ZeroReg)) {
7800 Patterns.push_back(Pattern);
7801 Found = true;
7802 }
7803 };
7804
7805 auto setShfFound = [&](int Opcode, unsigned ZeroReg, unsigned Pattern) {
7806 unsigned ShiftImm = Root.getOperand(3).getImm();
7808
7809 if ((ShiftTy != AArch64_AM::LSL && ShiftTy != AArch64_AM::LSR &&
7810 ShiftTy != AArch64_AM::ASR) ||
7811 AArch64_AM::getShiftValue(ShiftImm) == 0)
7812 return;
7813
7814 if (!canCombineWithMUL(MBB, Root.getOperand(1), Opcode, ZeroReg))
7815 return;
7816
7817 Patterns.push_back(Pattern);
7818 Found = true;
7819 };
7820
7821 auto setVFound = [&](int Opcode, int Operand, unsigned Pattern) {
7822 if (canCombine(MBB, Root.getOperand(Operand), Opcode)) {
7823 Patterns.push_back(Pattern);
7824 Found = true;
7825 }
7826 };
7827
7829
7830 switch (Opc) {
7831 default:
7832 break;
7833 case AArch64::ADDWrr:
7834 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
7835 "ADDWrr does not have register operands");
7836 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDW_OP1);
7837 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULADDW_OP2);
7838 break;
7839 case AArch64::ADDXrr:
7840 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDX_OP1);
7841 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULADDX_OP2);
7842 break;
7843 case AArch64::SUBWrr:
7844 setFound(AArch64::MADDWrrr, 2, AArch64::WZR, MCP::MULSUBW_OP2);
7845 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBW_OP1);
7846 break;
7847 case AArch64::SUBXrr:
7848 setFound(AArch64::MADDXrrr, 2, AArch64::XZR, MCP::MULSUBX_OP2);
7849 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBX_OP1);
7850 break;
7851 case AArch64::ADDWri:
7852 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULADDWI_OP1);
7853 break;
7854 case AArch64::ADDXri:
7855 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULADDXI_OP1);
7856 break;
7857 case AArch64::SUBWri:
7858 setFound(AArch64::MADDWrrr, 1, AArch64::WZR, MCP::MULSUBWI_OP1);
7859 break;
7860 case AArch64::SUBXri:
7861 setFound(AArch64::MADDXrrr, 1, AArch64::XZR, MCP::MULSUBXI_OP1);
7862 break;
7863 case AArch64::ADDWrs:
7864 setShfFound(AArch64::MADDWrrr, AArch64::WZR, MCP::MULADDWS_OP1);
7865 break;
7866 case AArch64::ADDXrs:
7867 setShfFound(AArch64::MADDXrrr, AArch64::XZR, MCP::MULADDXS_OP1);
7868 break;
7869 case AArch64::ADDv8i8:
7870 setVFound(AArch64::MULv8i8, 1, MCP::MULADDv8i8_OP1);
7871 setVFound(AArch64::MULv8i8, 2, MCP::MULADDv8i8_OP2);
7872 break;
7873 case AArch64::ADDv16i8:
7874 setVFound(AArch64::MULv16i8, 1, MCP::MULADDv16i8_OP1);
7875 setVFound(AArch64::MULv16i8, 2, MCP::MULADDv16i8_OP2);
7876 break;
7877 case AArch64::ADDv4i16:
7878 setVFound(AArch64::MULv4i16, 1, MCP::MULADDv4i16_OP1);
7879 setVFound(AArch64::MULv4i16, 2, MCP::MULADDv4i16_OP2);
7880 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULADDv4i16_indexed_OP1);
7881 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULADDv4i16_indexed_OP2);
7882 break;
7883 case AArch64::ADDv8i16:
7884 setVFound(AArch64::MULv8i16, 1, MCP::MULADDv8i16_OP1);
7885 setVFound(AArch64::MULv8i16, 2, MCP::MULADDv8i16_OP2);
7886 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULADDv8i16_indexed_OP1);
7887 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULADDv8i16_indexed_OP2);
7888 break;
7889 case AArch64::ADDv2i32:
7890 setVFound(AArch64::MULv2i32, 1, MCP::MULADDv2i32_OP1);
7891 setVFound(AArch64::MULv2i32, 2, MCP::MULADDv2i32_OP2);
7892 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULADDv2i32_indexed_OP1);
7893 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULADDv2i32_indexed_OP2);
7894 break;
7895 case AArch64::ADDv4i32:
7896 setVFound(AArch64::MULv4i32, 1, MCP::MULADDv4i32_OP1);
7897 setVFound(AArch64::MULv4i32, 2, MCP::MULADDv4i32_OP2);
7898 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULADDv4i32_indexed_OP1);
7899 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULADDv4i32_indexed_OP2);
7900 break;
7901 case AArch64::SUBv8i8:
7902 setVFound(AArch64::MULv8i8, 1, MCP::MULSUBv8i8_OP1);
7903 setVFound(AArch64::MULv8i8, 2, MCP::MULSUBv8i8_OP2);
7904 break;
7905 case AArch64::SUBv16i8:
7906 setVFound(AArch64::MULv16i8, 1, MCP::MULSUBv16i8_OP1);
7907 setVFound(AArch64::MULv16i8, 2, MCP::MULSUBv16i8_OP2);
7908 break;
7909 case AArch64::SUBv4i16:
7910 setVFound(AArch64::MULv4i16, 1, MCP::MULSUBv4i16_OP1);
7911 setVFound(AArch64::MULv4i16, 2, MCP::MULSUBv4i16_OP2);
7912 setVFound(AArch64::MULv4i16_indexed, 1, MCP::MULSUBv4i16_indexed_OP1);
7913 setVFound(AArch64::MULv4i16_indexed, 2, MCP::MULSUBv4i16_indexed_OP2);
7914 break;
7915 case AArch64::SUBv8i16:
7916 setVFound(AArch64::MULv8i16, 1, MCP::MULSUBv8i16_OP1);
7917 setVFound(AArch64::MULv8i16, 2, MCP::MULSUBv8i16_OP2);
7918 setVFound(AArch64::MULv8i16_indexed, 1, MCP::MULSUBv8i16_indexed_OP1);
7919 setVFound(AArch64::MULv8i16_indexed, 2, MCP::MULSUBv8i16_indexed_OP2);
7920 break;
7921 case AArch64::SUBv2i32:
7922 setVFound(AArch64::MULv2i32, 1, MCP::MULSUBv2i32_OP1);
7923 setVFound(AArch64::MULv2i32, 2, MCP::MULSUBv2i32_OP2);
7924 setVFound(AArch64::MULv2i32_indexed, 1, MCP::MULSUBv2i32_indexed_OP1);
7925 setVFound(AArch64::MULv2i32_indexed, 2, MCP::MULSUBv2i32_indexed_OP2);
7926 break;
7927 case AArch64::SUBv4i32:
7928 setVFound(AArch64::MULv4i32, 1, MCP::MULSUBv4i32_OP1);
7929 setVFound(AArch64::MULv4i32, 2, MCP::MULSUBv4i32_OP2);
7930 setVFound(AArch64::MULv4i32_indexed, 1, MCP::MULSUBv4i32_indexed_OP1);
7931 setVFound(AArch64::MULv4i32_indexed, 2, MCP::MULSUBv4i32_indexed_OP2);
7932 break;
7933 }
7934 return Found;
7935}
7936
7937bool AArch64InstrInfo::isAccumulationOpcode(unsigned Opcode) const {
7938 switch (Opcode) {
7939 default:
7940 break;
7941 case AArch64::UABALB_ZZZ_D:
7942 case AArch64::UABALB_ZZZ_H:
7943 case AArch64::UABALB_ZZZ_S:
7944 case AArch64::UABALT_ZZZ_D:
7945 case AArch64::UABALT_ZZZ_H:
7946 case AArch64::UABALT_ZZZ_S:
7947 case AArch64::SABALB_ZZZ_D:
7948 case AArch64::SABALB_ZZZ_S:
7949 case AArch64::SABALB_ZZZ_H:
7950 case AArch64::SABALT_ZZZ_D:
7951 case AArch64::SABALT_ZZZ_S:
7952 case AArch64::SABALT_ZZZ_H:
7953 case AArch64::UABALv16i8_v8i16:
7954 case AArch64::UABALv2i32_v2i64:
7955 case AArch64::UABALv4i16_v4i32:
7956 case AArch64::UABALv4i32_v2i64:
7957 case AArch64::UABALv8i16_v4i32:
7958 case AArch64::UABALv8i8_v8i16:
7959 case AArch64::UABAv16i8:
7960 case AArch64::UABAv2i32:
7961 case AArch64::UABAv4i16:
7962 case AArch64::UABAv4i32:
7963 case AArch64::UABAv8i16:
7964 case AArch64::UABAv8i8:
7965 case AArch64::SABALv16i8_v8i16:
7966 case AArch64::SABALv2i32_v2i64:
7967 case AArch64::SABALv4i16_v4i32:
7968 case AArch64::SABALv4i32_v2i64:
7969 case AArch64::SABALv8i16_v4i32:
7970 case AArch64::SABALv8i8_v8i16:
7971 case AArch64::SABAv16i8:
7972 case AArch64::SABAv2i32:
7973 case AArch64::SABAv4i16:
7974 case AArch64::SABAv4i32:
7975 case AArch64::SABAv8i16:
7976 case AArch64::SABAv8i8:
7977 return true;
7978 }
7979
7980 return false;
7981}
7982
7983unsigned AArch64InstrInfo::getAccumulationStartOpcode(
7984 unsigned AccumulationOpcode) const {
7985 switch (AccumulationOpcode) {
7986 default:
7987 llvm_unreachable("Unsupported accumulation Opcode!");
7988 case AArch64::UABALB_ZZZ_D:
7989 return AArch64::UABDLB_ZZZ_D;
7990 case AArch64::UABALB_ZZZ_H:
7991 return AArch64::UABDLB_ZZZ_H;
7992 case AArch64::UABALB_ZZZ_S:
7993 return AArch64::UABDLB_ZZZ_S;
7994 case AArch64::UABALT_ZZZ_D:
7995 return AArch64::UABDLT_ZZZ_D;
7996 case AArch64::UABALT_ZZZ_H:
7997 return AArch64::UABDLT_ZZZ_H;
7998 case AArch64::UABALT_ZZZ_S:
7999 return AArch64::UABDLT_ZZZ_S;
8000 case AArch64::UABALv16i8_v8i16:
8001 return AArch64::UABDLv16i8_v8i16;
8002 case AArch64::UABALv2i32_v2i64:
8003 return AArch64::UABDLv2i32_v2i64;
8004 case AArch64::UABALv4i16_v4i32:
8005 return AArch64::UABDLv4i16_v4i32;
8006 case AArch64::UABALv4i32_v2i64:
8007 return AArch64::UABDLv4i32_v2i64;
8008 case AArch64::UABALv8i16_v4i32:
8009 return AArch64::UABDLv8i16_v4i32;
8010 case AArch64::UABALv8i8_v8i16:
8011 return AArch64::UABDLv8i8_v8i16;
8012 case AArch64::UABAv16i8:
8013 return AArch64::UABDv16i8;
8014 case AArch64::UABAv2i32:
8015 return AArch64::UABDv2i32;
8016 case AArch64::UABAv4i16:
8017 return AArch64::UABDv4i16;
8018 case AArch64::UABAv4i32:
8019 return AArch64::UABDv4i32;
8020 case AArch64::UABAv8i16:
8021 return AArch64::UABDv8i16;
8022 case AArch64::UABAv8i8:
8023 return AArch64::UABDv8i8;
8024 case AArch64::SABALB_ZZZ_D:
8025 return AArch64::SABDLB_ZZZ_D;
8026 case AArch64::SABALB_ZZZ_S:
8027 return AArch64::SABDLB_ZZZ_S;
8028 case AArch64::SABALB_ZZZ_H:
8029 return AArch64::SABDLB_ZZZ_H;
8030 case AArch64::SABALT_ZZZ_D:
8031 return AArch64::SABDLT_ZZZ_D;
8032 case AArch64::SABALT_ZZZ_S:
8033 return AArch64::SABDLT_ZZZ_S;
8034 case AArch64::SABALT_ZZZ_H:
8035 return AArch64::SABDLT_ZZZ_H;
8036 case AArch64::SABALv16i8_v8i16:
8037 return AArch64::SABDLv16i8_v8i16;
8038 case AArch64::SABALv2i32_v2i64:
8039 return AArch64::SABDLv2i32_v2i64;
8040 case AArch64::SABALv4i16_v4i32:
8041 return AArch64::SABDLv4i16_v4i32;
8042 case AArch64::SABALv4i32_v2i64:
8043 return AArch64::SABDLv4i32_v2i64;
8044 case AArch64::SABALv8i16_v4i32:
8045 return AArch64::SABDLv8i16_v4i32;
8046 case AArch64::SABALv8i8_v8i16:
8047 return AArch64::SABDLv8i8_v8i16;
8048 case AArch64::SABAv16i8:
8049 return AArch64::SABDv16i8;
8050 case AArch64::SABAv2i32:
8051 return AArch64::SABDv2i32;
8052 case AArch64::SABAv4i16:
8053 return AArch64::SABDv4i16;
8054 case AArch64::SABAv4i32:
8055 return AArch64::SABDv4i32;
8056 case AArch64::SABAv8i16:
8057 return AArch64::SABDv8i16;
8058 case AArch64::SABAv8i8:
8059 return AArch64::SABDv8i8;
8060 }
8061}
8062
8063/// Floating-Point Support
8064
8065/// Find instructions that can be turned into madd.
8067 SmallVectorImpl<unsigned> &Patterns) {
8068
8069 if (!isCombineInstrCandidateFP(Root))
8070 return false;
8071
8072 MachineBasicBlock &MBB = *Root.getParent();
8073 bool Found = false;
8074
8075 auto Match = [&](int Opcode, int Operand, unsigned Pattern) -> bool {
8076 if (canCombineWithFMUL(MBB, Root.getOperand(Operand), Opcode)) {
8077 Patterns.push_back(Pattern);
8078 return true;
8079 }
8080 return false;
8081 };
8082
8084
8085 switch (Root.getOpcode()) {
8086 default:
8087 assert(false && "Unsupported FP instruction in combiner\n");
8088 break;
8089 case AArch64::FADDHrr:
8090 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
8091 "FADDHrr does not have register operands");
8092
8093 Found = Match(AArch64::FMULHrr, 1, MCP::FMULADDH_OP1);
8094 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULADDH_OP2);
8095 break;
8096 case AArch64::FADDSrr:
8097 assert(Root.getOperand(1).isReg() && Root.getOperand(2).isReg() &&
8098 "FADDSrr does not have register operands");
8099
8100 Found |= Match(AArch64::FMULSrr, 1, MCP::FMULADDS_OP1) ||
8101 Match(AArch64::FMULv1i32_indexed, 1, MCP::FMLAv1i32_indexed_OP1);
8102
8103 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULADDS_OP2) ||
8104 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLAv1i32_indexed_OP2);
8105 break;
8106 case AArch64::FADDDrr:
8107 Found |= Match(AArch64::FMULDrr, 1, MCP::FMULADDD_OP1) ||
8108 Match(AArch64::FMULv1i64_indexed, 1, MCP::FMLAv1i64_indexed_OP1);
8109
8110 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULADDD_OP2) ||
8111 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLAv1i64_indexed_OP2);
8112 break;
8113 case AArch64::FADDv4f16:
8114 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLAv4i16_indexed_OP1) ||
8115 Match(AArch64::FMULv4f16, 1, MCP::FMLAv4f16_OP1);
8116
8117 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLAv4i16_indexed_OP2) ||
8118 Match(AArch64::FMULv4f16, 2, MCP::FMLAv4f16_OP2);
8119 break;
8120 case AArch64::FADDv8f16:
8121 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLAv8i16_indexed_OP1) ||
8122 Match(AArch64::FMULv8f16, 1, MCP::FMLAv8f16_OP1);
8123
8124 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLAv8i16_indexed_OP2) ||
8125 Match(AArch64::FMULv8f16, 2, MCP::FMLAv8f16_OP2);
8126 break;
8127 case AArch64::FADDv2f32:
8128 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLAv2i32_indexed_OP1) ||
8129 Match(AArch64::FMULv2f32, 1, MCP::FMLAv2f32_OP1);
8130
8131 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLAv2i32_indexed_OP2) ||
8132 Match(AArch64::FMULv2f32, 2, MCP::FMLAv2f32_OP2);
8133 break;
8134 case AArch64::FADDv2f64:
8135 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLAv2i64_indexed_OP1) ||
8136 Match(AArch64::FMULv2f64, 1, MCP::FMLAv2f64_OP1);
8137
8138 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLAv2i64_indexed_OP2) ||
8139 Match(AArch64::FMULv2f64, 2, MCP::FMLAv2f64_OP2);
8140 break;
8141 case AArch64::FADDv4f32:
8142 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLAv4i32_indexed_OP1) ||
8143 Match(AArch64::FMULv4f32, 1, MCP::FMLAv4f32_OP1);
8144
8145 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLAv4i32_indexed_OP2) ||
8146 Match(AArch64::FMULv4f32, 2, MCP::FMLAv4f32_OP2);
8147 break;
8148 case AArch64::FSUBHrr:
8149 Found = Match(AArch64::FMULHrr, 1, MCP::FMULSUBH_OP1);
8150 Found |= Match(AArch64::FMULHrr, 2, MCP::FMULSUBH_OP2);
8151 Found |= Match(AArch64::FNMULHrr, 1, MCP::FNMULSUBH_OP1);
8152 break;
8153 case AArch64::FSUBSrr:
8154 Found = Match(AArch64::FMULSrr, 1, MCP::FMULSUBS_OP1);
8155
8156 Found |= Match(AArch64::FMULSrr, 2, MCP::FMULSUBS_OP2) ||
8157 Match(AArch64::FMULv1i32_indexed, 2, MCP::FMLSv1i32_indexed_OP2);
8158
8159 Found |= Match(AArch64::FNMULSrr, 1, MCP::FNMULSUBS_OP1);
8160 break;
8161 case AArch64::FSUBDrr:
8162 Found = Match(AArch64::FMULDrr, 1, MCP::FMULSUBD_OP1);
8163
8164 Found |= Match(AArch64::FMULDrr, 2, MCP::FMULSUBD_OP2) ||
8165 Match(AArch64::FMULv1i64_indexed, 2, MCP::FMLSv1i64_indexed_OP2);
8166
8167 Found |= Match(AArch64::FNMULDrr, 1, MCP::FNMULSUBD_OP1);
8168 break;
8169 case AArch64::FSUBv4f16:
8170 Found |= Match(AArch64::FMULv4i16_indexed, 2, MCP::FMLSv4i16_indexed_OP2) ||
8171 Match(AArch64::FMULv4f16, 2, MCP::FMLSv4f16_OP2);
8172
8173 Found |= Match(AArch64::FMULv4i16_indexed, 1, MCP::FMLSv4i16_indexed_OP1) ||
8174 Match(AArch64::FMULv4f16, 1, MCP::FMLSv4f16_OP1);
8175 break;
8176 case AArch64::FSUBv8f16:
8177 Found |= Match(AArch64::FMULv8i16_indexed, 2, MCP::FMLSv8i16_indexed_OP2) ||
8178 Match(AArch64::FMULv8f16, 2, MCP::FMLSv8f16_OP2);
8179
8180 Found |= Match(AArch64::FMULv8i16_indexed, 1, MCP::FMLSv8i16_indexed_OP1) ||
8181 Match(AArch64::FMULv8f16, 1, MCP::FMLSv8f16_OP1);
8182 break;
8183 case AArch64::FSUBv2f32:
8184 Found |= Match(AArch64::FMULv2i32_indexed, 2, MCP::FMLSv2i32_indexed_OP2) ||
8185 Match(AArch64::FMULv2f32, 2, MCP::FMLSv2f32_OP2);
8186
8187 Found |= Match(AArch64::FMULv2i32_indexed, 1, MCP::FMLSv2i32_indexed_OP1) ||
8188 Match(AArch64::FMULv2f32, 1, MCP::FMLSv2f32_OP1);
8189 break;
8190 case AArch64::FSUBv2f64:
8191 Found |= Match(AArch64::FMULv2i64_indexed, 2, MCP::FMLSv2i64_indexed_OP2) ||
8192 Match(AArch64::FMULv2f64, 2, MCP::FMLSv2f64_OP2);
8193
8194 Found |= Match(AArch64::FMULv2i64_indexed, 1, MCP::FMLSv2i64_indexed_OP1) ||
8195 Match(AArch64::FMULv2f64, 1, MCP::FMLSv2f64_OP1);
8196 break;
8197 case AArch64::FSUBv4f32:
8198 Found |= Match(AArch64::FMULv4i32_indexed, 2, MCP::FMLSv4i32_indexed_OP2) ||
8199 Match(AArch64::FMULv4f32, 2, MCP::FMLSv4f32_OP2);
8200
8201 Found |= Match(AArch64::FMULv4i32_indexed, 1, MCP::FMLSv4i32_indexed_OP1) ||
8202 Match(AArch64::FMULv4f32, 1, MCP::FMLSv4f32_OP1);
8203 break;
8204 }
8205 return Found;
8206}
8207
8209 SmallVectorImpl<unsigned> &Patterns) {
8210 MachineBasicBlock &MBB = *Root.getParent();
8211 bool Found = false;
8212
8213 auto Match = [&](unsigned Opcode, int Operand, unsigned Pattern) -> bool {
8214 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8215 MachineOperand &MO = Root.getOperand(Operand);
8216 MachineInstr *MI = nullptr;
8217 if (MO.isReg() && MO.getReg().isVirtual())
8218 MI = MRI.getUniqueVRegDef(MO.getReg());
8219 // Ignore No-op COPYs in FMUL(COPY(DUP(..)))
8220 if (MI && MI->getOpcode() == TargetOpcode::COPY &&
8221 MI->getOperand(1).getReg().isVirtual())
8222 MI = MRI.getUniqueVRegDef(MI->getOperand(1).getReg());
8223 if (MI && MI->getOpcode() == Opcode) {
8224 Patterns.push_back(Pattern);
8225 return true;
8226 }
8227 return false;
8228 };
8229
8231
8232 switch (Root.getOpcode()) {
8233 default:
8234 return false;
8235 case AArch64::FMULv2f32:
8236 Found = Match(AArch64::DUPv2i32lane, 1, MCP::FMULv2i32_indexed_OP1);
8237 Found |= Match(AArch64::DUPv2i32lane, 2, MCP::FMULv2i32_indexed_OP2);
8238 break;
8239 case AArch64::FMULv2f64:
8240 Found = Match(AArch64::DUPv2i64lane, 1, MCP::FMULv2i64_indexed_OP1);
8241 Found |= Match(AArch64::DUPv2i64lane, 2, MCP::FMULv2i64_indexed_OP2);
8242 break;
8243 case AArch64::FMULv4f16:
8244 Found = Match(AArch64::DUPv4i16lane, 1, MCP::FMULv4i16_indexed_OP1);
8245 Found |= Match(AArch64::DUPv4i16lane, 2, MCP::FMULv4i16_indexed_OP2);
8246 break;
8247 case AArch64::FMULv4f32:
8248 Found = Match(AArch64::DUPv4i32lane, 1, MCP::FMULv4i32_indexed_OP1);
8249 Found |= Match(AArch64::DUPv4i32lane, 2, MCP::FMULv4i32_indexed_OP2);
8250 break;
8251 case AArch64::FMULv8f16:
8252 Found = Match(AArch64::DUPv8i16lane, 1, MCP::FMULv8i16_indexed_OP1);
8253 Found |= Match(AArch64::DUPv8i16lane, 2, MCP::FMULv8i16_indexed_OP2);
8254 break;
8255 }
8256
8257 return Found;
8258}
8259
8261 SmallVectorImpl<unsigned> &Patterns) {
8262 unsigned Opc = Root.getOpcode();
8263 MachineBasicBlock &MBB = *Root.getParent();
8264 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
8265
8266 auto Match = [&](unsigned Opcode, unsigned Pattern) -> bool {
8267 MachineOperand &MO = Root.getOperand(1);
8268 MachineInstr *MI = MRI.getUniqueVRegDef(MO.getReg());
8269 if (MI != nullptr && (MI->getOpcode() == Opcode) &&
8270 MRI.hasOneNonDBGUse(MI->getOperand(0).getReg()) &&
8274 MI->getFlag(MachineInstr::MIFlag::FmNsz)) {
8275 Patterns.push_back(Pattern);
8276 return true;
8277 }
8278 return false;
8279 };
8280
8281 switch (Opc) {
8282 default:
8283 break;
8284 case AArch64::FNEGDr:
8285 return Match(AArch64::FMADDDrrr, AArch64MachineCombinerPattern::FNMADD);
8286 case AArch64::FNEGSr:
8287 return Match(AArch64::FMADDSrrr, AArch64MachineCombinerPattern::FNMADD);
8288 }
8289
8290 return false;
8291}
8292
8293/// Return true when a code sequence can improve throughput. It
8294/// should be called only for instructions in loops.
8295/// \param Pattern - combiner pattern
8297 switch (Pattern) {
8298 default:
8299 break;
8405 return true;
8406 } // end switch (Pattern)
8407 return false;
8408}
8409
8410/// Find other MI combine patterns.
8412 SmallVectorImpl<unsigned> &Patterns) {
8413 // A - (B + C) ==> (A - B) - C or (A - C) - B
8414 unsigned Opc = Root.getOpcode();
8415 MachineBasicBlock &MBB = *Root.getParent();
8416
8417 switch (Opc) {
8418 case AArch64::SUBWrr:
8419 case AArch64::SUBSWrr:
8420 case AArch64::SUBXrr:
8421 case AArch64::SUBSXrr:
8422 // Found candidate root.
8423 break;
8424 default:
8425 return false;
8426 }
8427
8429 Root.findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr, true) ==
8430 -1)
8431 return false;
8432
8433 if (canCombine(MBB, Root.getOperand(2), AArch64::ADDWrr) ||
8434 canCombine(MBB, Root.getOperand(2), AArch64::ADDSWrr) ||
8435 canCombine(MBB, Root.getOperand(2), AArch64::ADDXrr) ||
8436 canCombine(MBB, Root.getOperand(2), AArch64::ADDSXrr)) {
8439 return true;
8440 }
8441
8442 return false;
8443}
8444
8445/// Check if the given instruction forms a gather load pattern that can be
8446/// optimized for better Memory-Level Parallelism (MLP). This function
8447/// identifies chains of NEON lane load instructions that load data from
8448/// different memory addresses into individual lanes of a 128-bit vector
8449/// register, then attempts to split the pattern into parallel loads to break
8450/// the serial dependency between instructions.
8451///
8452/// Pattern Matched:
8453/// Initial scalar load -> SUBREG_TO_REG (lane 0) -> LD1i* (lane 1) ->
8454/// LD1i* (lane 2) -> ... -> LD1i* (lane N-1, Root)
8455///
8456/// Transformed Into:
8457/// Two parallel vector loads using fewer lanes each, followed by ZIP1v2i64
8458/// to combine the results, enabling better memory-level parallelism.
8459///
8460/// Supported Element Types:
8461/// - 32-bit elements (LD1i32, 4 lanes total)
8462/// - 16-bit elements (LD1i16, 8 lanes total)
8463/// - 8-bit elements (LD1i8, 16 lanes total)
8465 SmallVectorImpl<unsigned> &Patterns,
8466 unsigned LoadLaneOpCode, unsigned NumLanes) {
8467 const MachineFunction *MF = Root.getMF();
8468
8469 // Early exit if optimizing for size.
8470 if (MF->getFunction().hasMinSize())
8471 return false;
8472
8473 const MachineRegisterInfo &MRI = MF->getRegInfo();
8475
8476 // The root of the pattern must load into the last lane of the vector.
8477 if (Root.getOperand(2).getImm() != NumLanes - 1)
8478 return false;
8479
8480 // Check that we have load into all lanes except lane 0.
8481 // For each load we also want to check that:
8482 // 1. It has a single non-debug use (since we will be replacing the virtual
8483 // register)
8484 // 2. That the addressing mode only uses a single pointer operand
8485 auto *CurrInstr = MRI.getUniqueVRegDef(Root.getOperand(1).getReg());
8486 auto Range = llvm::seq<unsigned>(1, NumLanes - 1);
8487 SmallSet<unsigned, 16> RemainingLanes(Range.begin(), Range.end());
8489 while (!RemainingLanes.empty() && CurrInstr &&
8490 CurrInstr->getOpcode() == LoadLaneOpCode &&
8491 MRI.hasOneNonDBGUse(CurrInstr->getOperand(0).getReg()) &&
8492 CurrInstr->getNumOperands() == 4) {
8493 RemainingLanes.erase(CurrInstr->getOperand(2).getImm());
8494 LoadInstrs.push_back(CurrInstr);
8495 CurrInstr = MRI.getUniqueVRegDef(CurrInstr->getOperand(1).getReg());
8496 }
8497
8498 // Check that we have found a match for lanes N-1.. 1.
8499 if (!RemainingLanes.empty())
8500 return false;
8501
8502 // Match the SUBREG_TO_REG sequence.
8503 if (CurrInstr->getOpcode() != TargetOpcode::SUBREG_TO_REG)
8504 return false;
8505
8506 // Verify that the subreg to reg loads an integer into the first lane.
8507 auto Lane0LoadReg = CurrInstr->getOperand(1).getReg();
8508 unsigned SingleLaneSizeInBits = 128 / NumLanes;
8509 if (TRI->getRegSizeInBits(Lane0LoadReg, MRI) != SingleLaneSizeInBits)
8510 return false;
8511
8512 // Verify that it also has a single non debug use.
8513 if (!MRI.hasOneNonDBGUse(Lane0LoadReg))
8514 return false;
8515
8516 LoadInstrs.push_back(MRI.getUniqueVRegDef(Lane0LoadReg));
8517
8518 // If there is any chance of aliasing, do not apply the pattern.
8519 // Walk backward through the MBB starting from Root.
8520 // Exit early if we've encountered all load instructions or hit the search
8521 // limit.
8522 auto MBBItr = Root.getIterator();
8523 unsigned RemainingSteps =
8524 MF->getSubtarget<AArch64Subtarget>().getCLOpts().search_limit;
8525 SmallPtrSet<const MachineInstr *, 16> RemainingLoadInstrs;
8526 RemainingLoadInstrs.insert(LoadInstrs.begin(), LoadInstrs.end());
8527 const MachineBasicBlock *MBB = Root.getParent();
8528
8529 for (; MBBItr != MBB->begin() && RemainingSteps > 0 &&
8530 !RemainingLoadInstrs.empty();
8531 --MBBItr, --RemainingSteps) {
8532 const MachineInstr &CurrInstr = *MBBItr;
8533
8534 // Remove this instruction from remaining loads if it's one we're tracking.
8535 RemainingLoadInstrs.erase(&CurrInstr);
8536
8537 // Check for potential aliasing with any of the load instructions to
8538 // optimize.
8539 if (CurrInstr.isLoadFoldBarrier())
8540 return false;
8541 }
8542
8543 // If we hit the search limit without finding all load instructions,
8544 // don't match the pattern.
8545 if (RemainingSteps == 0 && !RemainingLoadInstrs.empty())
8546 return false;
8547
8548 switch (NumLanes) {
8549 case 4:
8551 break;
8552 case 8:
8554 break;
8555 case 16:
8557 break;
8558 default:
8559 llvm_unreachable("Got bad number of lanes for gather pattern.");
8560 }
8561
8562 return true;
8563}
8564
8565/// Search for patterns of LD instructions we can optimize.
8567 SmallVectorImpl<unsigned> &Patterns) {
8568
8569 // The pattern searches for loads into single lanes.
8570 switch (Root.getOpcode()) {
8571 case AArch64::LD1i32:
8572 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 4);
8573 case AArch64::LD1i16:
8574 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 8);
8575 case AArch64::LD1i8:
8576 return getGatherLanePattern(Root, Patterns, Root.getOpcode(), 16);
8577 default:
8578 return false;
8579 }
8580}
8581
8582/// Generate optimized instruction sequence for gather load patterns to improve
8583/// Memory-Level Parallelism (MLP). This function transforms a chain of
8584/// sequential NEON lane loads into parallel vector loads that can execute
8585/// concurrently.
8586static void
8590 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
8591 unsigned Pattern, unsigned NumLanes) {
8592 MachineFunction &MF = *Root.getParent()->getParent();
8595
8596 // Gather the initial load instructions to build the pattern.
8597 SmallVector<MachineInstr *, 16> LoadToLaneInstrs;
8598 MachineInstr *CurrInstr = &Root;
8599 for (unsigned i = 0; i < NumLanes - 1; ++i) {
8600 LoadToLaneInstrs.push_back(CurrInstr);
8601 CurrInstr = MRI.getUniqueVRegDef(CurrInstr->getOperand(1).getReg());
8602 }
8603
8604 // Sort the load instructions according to the lane.
8605 llvm::sort(LoadToLaneInstrs,
8606 [](const MachineInstr *A, const MachineInstr *B) {
8607 return A->getOperand(2).getImm() > B->getOperand(2).getImm();
8608 });
8609
8610 MachineInstr *SubregToReg = CurrInstr;
8611 LoadToLaneInstrs.push_back(
8612 MRI.getUniqueVRegDef(SubregToReg->getOperand(1).getReg()));
8613 auto LoadToLaneInstrsAscending = llvm::reverse(LoadToLaneInstrs);
8614
8615 const TargetRegisterClass *FPR128RegClass =
8616 MRI.getRegClass(Root.getOperand(0).getReg());
8617
8618 // Helper lambda to create a LD1 instruction.
8619 auto CreateLD1Instruction = [&](MachineInstr *OriginalInstr,
8620 Register SrcRegister, unsigned Lane,
8621 Register OffsetRegister) {
8622 auto NewRegister = MRI.createVirtualRegister(FPR128RegClass);
8623 MachineInstrBuilder LoadIndexIntoRegister =
8624 BuildMI(MF, MIMetadata(*OriginalInstr), TII->get(Root.getOpcode()),
8625 NewRegister)
8626 .addReg(SrcRegister)
8627 .addImm(Lane)
8628 .addReg(OffsetRegister)
8629 .setMemRefs(OriginalInstr->memoperands());
8630 InstrIdxForVirtReg.insert(std::make_pair(NewRegister, InsInstrs.size()));
8631 InsInstrs.push_back(LoadIndexIntoRegister);
8632 return NewRegister;
8633 };
8634
8635 // Helper to create load instruction based on the NumLanes in the NEON
8636 // register we are rewriting.
8637 auto CreateLDRInstruction =
8638 [&](unsigned NumLanes, Register DestReg, Register OffsetReg,
8640 unsigned Opcode;
8641 switch (NumLanes) {
8642 case 4:
8643 Opcode = AArch64::LDRSui;
8644 break;
8645 case 8:
8646 Opcode = AArch64::LDRHui;
8647 break;
8648 case 16:
8649 Opcode = AArch64::LDRBui;
8650 break;
8651 default:
8653 "Got unsupported number of lanes in machine-combiner gather pattern");
8654 }
8655 // Immediate offset load
8656 return BuildMI(MF, MIMetadata(Root), TII->get(Opcode), DestReg)
8657 .addReg(OffsetReg)
8658 .addImm(0)
8659 .setMemRefs(MMOs);
8660 };
8661
8662 // Load the remaining lanes into register 0.
8663 auto LanesToLoadToReg0 =
8664 llvm::make_range(LoadToLaneInstrsAscending.begin() + 1,
8665 LoadToLaneInstrsAscending.begin() + NumLanes / 2);
8666 Register PrevReg = SubregToReg->getOperand(0).getReg();
8667 for (auto [Index, LoadInstr] : llvm::enumerate(LanesToLoadToReg0)) {
8668 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8669 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8670 OffsetRegOperand.getReg());
8671 DelInstrs.push_back(LoadInstr);
8672 }
8673 Register LastLoadReg0 = PrevReg;
8674
8675 // First load into register 1. Perform an integer load to zero out the upper
8676 // lanes in a single instruction.
8677 MachineInstr *Lane0Load = *LoadToLaneInstrsAscending.begin();
8678 MachineInstr *OriginalSplitLoad =
8679 *std::next(LoadToLaneInstrsAscending.begin(), NumLanes / 2);
8680 Register DestRegForMiddleIndex = MRI.createVirtualRegister(
8681 MRI.getRegClass(Lane0Load->getOperand(0).getReg()));
8682
8683 const MachineOperand &OriginalSplitToLoadOffsetOperand =
8684 OriginalSplitLoad->getOperand(3);
8685 MachineInstrBuilder MiddleIndexLoadInstr =
8686 CreateLDRInstruction(NumLanes, DestRegForMiddleIndex,
8687 OriginalSplitToLoadOffsetOperand.getReg(),
8688 OriginalSplitLoad->memoperands());
8689
8690 InstrIdxForVirtReg.insert(
8691 std::make_pair(DestRegForMiddleIndex, InsInstrs.size()));
8692 InsInstrs.push_back(MiddleIndexLoadInstr);
8693 DelInstrs.push_back(OriginalSplitLoad);
8694
8695 // Subreg To Reg instruction for register 1.
8696 Register DestRegForSubregToReg = MRI.createVirtualRegister(FPR128RegClass);
8697 unsigned SubregType;
8698 switch (NumLanes) {
8699 case 4:
8700 SubregType = AArch64::ssub;
8701 break;
8702 case 8:
8703 SubregType = AArch64::hsub;
8704 break;
8705 case 16:
8706 SubregType = AArch64::bsub;
8707 break;
8708 default:
8710 "Got invalid NumLanes for machine-combiner gather pattern");
8711 }
8712
8713 auto SubRegToRegInstr =
8714 BuildMI(MF, MIMetadata(Root), TII->get(SubregToReg->getOpcode()),
8715 DestRegForSubregToReg)
8716 .addReg(DestRegForMiddleIndex)
8717 .addImm(SubregType);
8718 InstrIdxForVirtReg.insert(
8719 std::make_pair(DestRegForSubregToReg, InsInstrs.size()));
8720 InsInstrs.push_back(SubRegToRegInstr);
8721
8722 // Load remaining lanes into register 1.
8723 auto LanesToLoadToReg1 =
8724 llvm::make_range(LoadToLaneInstrsAscending.begin() + NumLanes / 2 + 1,
8725 LoadToLaneInstrsAscending.end());
8726 PrevReg = SubRegToRegInstr->getOperand(0).getReg();
8727 for (auto [Index, LoadInstr] : llvm::enumerate(LanesToLoadToReg1)) {
8728 const MachineOperand &OffsetRegOperand = LoadInstr->getOperand(3);
8729 PrevReg = CreateLD1Instruction(LoadInstr, PrevReg, Index + 1,
8730 OffsetRegOperand.getReg());
8731
8732 // Do not add the last reg to DelInstrs - it will be removed later.
8733 if (Index == NumLanes / 2 - 2) {
8734 break;
8735 }
8736 DelInstrs.push_back(LoadInstr);
8737 }
8738 Register LastLoadReg1 = PrevReg;
8739
8740 // Create the final zip instruction to combine the results.
8741 MachineInstrBuilder ZipInstr =
8742 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::ZIP1v2i64),
8743 Root.getOperand(0).getReg())
8744 .addReg(LastLoadReg0)
8745 .addReg(LastLoadReg1);
8746 InsInstrs.push_back(ZipInstr);
8747}
8748
8762
8763/// Return true when there is potentially a faster code sequence for an
8764/// instruction chain ending in \p Root. All potential patterns are listed in
8765/// the \p Pattern vector. Pattern should be sorted in priority order since the
8766/// pattern evaluator stops checking as soon as it finds a faster sequence.
8767
8768bool AArch64InstrInfo::getMachineCombinerPatterns(
8769 MachineInstr &Root, SmallVectorImpl<unsigned> &Patterns,
8770 bool DoRegPressureReduce) const {
8771 // Integer patterns
8772 if (getMaddPatterns(Root, Patterns))
8773 return true;
8774 // Floating point patterns
8775 if (getFMULPatterns(Root, Patterns))
8776 return true;
8777 if (getFMAPatterns(Root, Patterns))
8778 return true;
8779 if (getFNEGPatterns(Root, Patterns))
8780 return true;
8781
8782 // Other patterns
8783 if (getMiscPatterns(Root, Patterns))
8784 return true;
8785
8786 // Load patterns
8787 if (getLoadPatterns(Root, Patterns))
8788 return true;
8789
8790 return TargetInstrInfo::getMachineCombinerPatterns(Root, Patterns,
8791 DoRegPressureReduce);
8792}
8793
8795/// genFusedMultiply - Generate fused multiply instructions.
8796/// This function supports both integer and floating point instructions.
8797/// A typical example:
8798/// F|MUL I=A,B,0
8799/// F|ADD R,I,C
8800/// ==> F|MADD R,A,B,C
8801/// \param MF Containing MachineFunction
8802/// \param MRI Register information
8803/// \param TII Target information
8804/// \param Root is the F|ADD instruction
8805/// \param [out] InsInstrs is a vector of machine instructions and will
8806/// contain the generated madd instruction
8807/// \param IdxMulOpd is index of operand in Root that is the result of
8808/// the F|MUL. In the example above IdxMulOpd is 1.
8809/// \param MaddOpc the opcode fo the f|madd instruction
8810/// \param RC Register class of operands
8811/// \param kind of fma instruction (addressing mode) to be generated
8812/// \param ReplacedAddend is the result register from the instruction
8813/// replacing the non-combined operand, if any.
8814static MachineInstr *
8816 const TargetInstrInfo *TII, MachineInstr &Root,
8817 SmallVectorImpl<MachineInstr *> &InsInstrs, unsigned IdxMulOpd,
8818 unsigned MaddOpc, const TargetRegisterClass *RC,
8820 const Register *ReplacedAddend = nullptr) {
8821 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
8822
8823 unsigned IdxOtherOpd = IdxMulOpd == 1 ? 2 : 1;
8824 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
8825 Register ResultReg = Root.getOperand(0).getReg();
8826 Register SrcReg0 = MUL->getOperand(1).getReg();
8827 Register SrcReg1 = MUL->getOperand(2).getReg();
8828
8829 Register SrcReg2 =
8830 ReplacedAddend ? *ReplacedAddend : Root.getOperand(IdxOtherOpd).getReg();
8831
8832 if (ResultReg.isVirtual())
8833 MRI.constrainRegClass(ResultReg, RC);
8834 if (SrcReg0.isVirtual())
8835 MRI.constrainRegClass(SrcReg0, RC);
8836 if (SrcReg1.isVirtual())
8837 MRI.constrainRegClass(SrcReg1, RC);
8838 if (SrcReg2.isVirtual())
8839 MRI.constrainRegClass(SrcReg2, RC);
8840
8842 if (kind == FMAInstKind::Default)
8843 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8844 .addReg(SrcReg0)
8845 .addReg(SrcReg1)
8846 .addReg(SrcReg2);
8847 else if (kind == FMAInstKind::Indexed)
8848 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8849 .addReg(SrcReg2)
8850 .addReg(SrcReg0)
8851 .addReg(SrcReg1)
8852 .addImm(MUL->getOperand(3).getImm());
8853 else if (kind == FMAInstKind::Accumulator)
8854 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8855 .addReg(SrcReg2)
8856 .addReg(SrcReg0)
8857 .addReg(SrcReg1);
8858 else
8859 assert(false && "Invalid FMA instruction kind \n");
8860 // Insert the MADD (MADD, FMA, FMS, FMLA, FMSL)
8861 InsInstrs.push_back(MIB);
8862 return MUL;
8863}
8864
8865/// MUL I=A,B,0
8866/// ADDrs R,I,C,shift
8867/// ==>
8868/// SBFM/UBFM J=C,shift
8869/// MADD R,A,B,J
8871 const TargetInstrInfo *TII, MachineInstr &Root,
8874 unsigned MaddOpc, bool Is64Bit,
8875 DenseMap<Register, unsigned> &InstrIdxForVirtReg) {
8876 const TargetRegisterClass *RC =
8877 Is64Bit ? &AArch64::GPR64RegClass : &AArch64::GPR32RegClass;
8878 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(1).getReg());
8879 Register ResultReg = Root.getOperand(0).getReg();
8880 Register SrcReg0 = MUL->getOperand(1).getReg();
8881 Register SrcReg1 = MUL->getOperand(2).getReg();
8882 Register ShiftedReg = Root.getOperand(2).getReg();
8883
8884 if (ResultReg.isVirtual())
8885 MRI.constrainRegClass(ResultReg, RC);
8886 if (SrcReg0.isVirtual())
8887 MRI.constrainRegClass(SrcReg0, RC);
8888 if (SrcReg1.isVirtual())
8889 MRI.constrainRegClass(SrcReg1, RC);
8890 if (ShiftedReg.isVirtual())
8891 MRI.constrainRegClass(ShiftedReg, RC);
8892
8893 unsigned ShiftImm = Root.getOperand(3).getImm();
8894 unsigned ShiftVal = AArch64_AM::getShiftValue(ShiftImm);
8895 unsigned RegSize = Is64Bit ? 64 : 32;
8896 unsigned BFMOpc;
8897 unsigned ImmR, ImmS;
8898 switch (AArch64_AM::getShiftType(ShiftImm)) {
8899 case AArch64_AM::ASR:
8900 BFMOpc = Is64Bit ? AArch64::SBFMXri : AArch64::SBFMWri;
8901 ImmR = ShiftVal;
8902 ImmS = RegSize - 1;
8903 break;
8904 case AArch64_AM::LSR:
8905 BFMOpc = Is64Bit ? AArch64::UBFMXri : AArch64::UBFMWri;
8906 ImmR = ShiftVal;
8907 ImmS = RegSize - 1;
8908 break;
8909 case AArch64_AM::LSL:
8910 BFMOpc = Is64Bit ? AArch64::UBFMXri : AArch64::UBFMWri;
8911 ImmR = (RegSize - ShiftVal) % RegSize;
8912 ImmS = RegSize - 1 - ShiftVal;
8913 break;
8914 default:
8915 llvm_unreachable("Unexpected shift type");
8916 }
8917
8918 Register ShiftReg = MRI.createVirtualRegister(RC);
8919 MachineInstrBuilder MIB1 =
8920 BuildMI(MF, MIMetadata(Root), TII->get(BFMOpc), ShiftReg)
8921 .addReg(ShiftedReg)
8922 .addImm(ImmR)
8923 .addImm(ImmS);
8924 InstrIdxForVirtReg.insert(std::make_pair(ShiftReg, InsInstrs.size()));
8925 InsInstrs.push_back(MIB1);
8926
8927 uint32_t Flags = Root.getFlags() & MUL->getFlags() &
8929
8930 MachineInstrBuilder MIB2 =
8931 BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
8932 .addReg(SrcReg0)
8933 .addReg(SrcReg1)
8934 .addReg(ShiftReg)
8935 .setMIFlags(Flags);
8936
8937 InsInstrs.push_back(MIB2);
8938 DelInstrs.push_back(MUL);
8939 DelInstrs.push_back(&Root);
8940}
8941
8942static MachineInstr *
8944 const TargetInstrInfo *TII, MachineInstr &Root,
8946 MachineInstr *MAD = MRI.getUniqueVRegDef(Root.getOperand(1).getReg());
8947
8948 unsigned Opc = 0;
8949 const TargetRegisterClass *RC = MRI.getRegClass(MAD->getOperand(0).getReg());
8950 if (AArch64::FPR32RegClass.hasSubClassEq(RC))
8951 Opc = AArch64::FNMADDSrrr;
8952 else if (AArch64::FPR64RegClass.hasSubClassEq(RC))
8953 Opc = AArch64::FNMADDDrrr;
8954 else
8955 return nullptr;
8956
8957 Register ResultReg = Root.getOperand(0).getReg();
8958 Register SrcReg0 = MAD->getOperand(1).getReg();
8959 Register SrcReg1 = MAD->getOperand(2).getReg();
8960 Register SrcReg2 = MAD->getOperand(3).getReg();
8961 if (ResultReg.isVirtual())
8962 MRI.constrainRegClass(ResultReg, RC);
8963 if (SrcReg0.isVirtual())
8964 MRI.constrainRegClass(SrcReg0, RC);
8965 if (SrcReg1.isVirtual())
8966 MRI.constrainRegClass(SrcReg1, RC);
8967 if (SrcReg2.isVirtual())
8968 MRI.constrainRegClass(SrcReg2, RC);
8969
8971 BuildMI(MF, MIMetadata(Root), TII->get(Opc), ResultReg)
8972 .addReg(SrcReg0)
8973 .addReg(SrcReg1)
8974 .addReg(SrcReg2);
8975 InsInstrs.push_back(MIB);
8976
8977 return MAD;
8978}
8979
8980/// Fold (FMUL x (DUP y lane)) into (FMUL_indexed x y lane)
8981static MachineInstr *
8984 unsigned IdxDupOp, unsigned MulOpc,
8986 assert(((IdxDupOp == 1) || (IdxDupOp == 2)) &&
8987 "Invalid index of FMUL operand");
8988
8989 MachineFunction &MF = *Root.getMF();
8991
8992 MachineInstr *Dup =
8993 MF.getRegInfo().getUniqueVRegDef(Root.getOperand(IdxDupOp).getReg());
8994
8995 if (Dup->getOpcode() == TargetOpcode::COPY)
8996 Dup = MRI.getUniqueVRegDef(Dup->getOperand(1).getReg());
8997
8998 Register DupSrcReg = Dup->getOperand(1).getReg();
8999 MRI.clearKillFlags(DupSrcReg);
9000 MRI.constrainRegClass(DupSrcReg, RC);
9001
9002 unsigned DupSrcLane = Dup->getOperand(2).getImm();
9003
9004 unsigned IdxMulOp = IdxDupOp == 1 ? 2 : 1;
9005 MachineOperand &MulOp = Root.getOperand(IdxMulOp);
9006
9007 Register ResultReg = Root.getOperand(0).getReg();
9008
9010 MIB = BuildMI(MF, MIMetadata(Root), TII->get(MulOpc), ResultReg)
9011 .add(MulOp)
9012 .addReg(DupSrcReg)
9013 .addImm(DupSrcLane);
9014
9015 InsInstrs.push_back(MIB);
9016 return &Root;
9017}
9018
9019/// genFusedMultiplyAcc - Helper to generate fused multiply accumulate
9020/// instructions.
9021///
9022/// \see genFusedMultiply
9026 unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC) {
9027 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
9029}
9030
9031/// genNeg - Helper to generate an intermediate negation of the second operand
9032/// of Root
9034 const TargetInstrInfo *TII, MachineInstr &Root,
9036 DenseMap<Register, unsigned> &InstrIdxForVirtReg,
9037 unsigned MnegOpc, const TargetRegisterClass *RC) {
9038 Register NewVR = MRI.createVirtualRegister(RC);
9040 BuildMI(MF, MIMetadata(Root), TII->get(MnegOpc), NewVR)
9041 .add(Root.getOperand(2));
9042 InsInstrs.push_back(MIB);
9043
9044 assert(InstrIdxForVirtReg.empty());
9045 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9046
9047 return NewVR;
9048}
9049
9050/// genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate
9051/// instructions with an additional negation of the accumulator
9055 DenseMap<Register, unsigned> &InstrIdxForVirtReg, unsigned IdxMulOpd,
9056 unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC) {
9057 assert(IdxMulOpd == 1);
9058
9059 Register NewVR =
9060 genNeg(MF, MRI, TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
9061 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
9062 FMAInstKind::Accumulator, &NewVR);
9063}
9064
9065/// genFusedMultiplyIdx - Helper to generate fused multiply accumulate
9066/// instructions.
9067///
9068/// \see genFusedMultiply
9072 unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC) {
9073 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
9075}
9076
9077/// genFusedMultiplyAccNeg - Helper to generate fused multiply accumulate
9078/// instructions with an additional negation of the accumulator
9082 DenseMap<Register, unsigned> &InstrIdxForVirtReg, unsigned IdxMulOpd,
9083 unsigned MaddOpc, unsigned MnegOpc, const TargetRegisterClass *RC) {
9084 assert(IdxMulOpd == 1);
9085
9086 Register NewVR =
9087 genNeg(MF, MRI, TII, Root, InsInstrs, InstrIdxForVirtReg, MnegOpc, RC);
9088
9089 return genFusedMultiply(MF, MRI, TII, Root, InsInstrs, IdxMulOpd, MaddOpc, RC,
9090 FMAInstKind::Indexed, &NewVR);
9091}
9092
9093/// genMaddR - Generate madd instruction and combine mul and add using
9094/// an extra virtual register
9095/// Example - an ADD intermediate needs to be stored in a register:
9096/// MUL I=A,B,0
9097/// ADD R,I,Imm
9098/// ==> ORR V, ZR, Imm
9099/// ==> MADD R,A,B,V
9100/// \param MF Containing MachineFunction
9101/// \param MRI Register information
9102/// \param TII Target information
9103/// \param Root is the ADD instruction
9104/// \param [out] InsInstrs is a vector of machine instructions and will
9105/// contain the generated madd instruction
9106/// \param IdxMulOpd is index of operand in Root that is the result of
9107/// the MUL. In the example above IdxMulOpd is 1.
9108/// \param MaddOpc the opcode fo the madd instruction
9109/// \param VR is a virtual register that holds the value of an ADD operand
9110/// (V in the example above).
9111/// \param RC Register class of operands
9113 const TargetInstrInfo *TII, MachineInstr &Root,
9115 unsigned IdxMulOpd, unsigned MaddOpc, unsigned VR,
9116 const TargetRegisterClass *RC) {
9117 assert(IdxMulOpd == 1 || IdxMulOpd == 2);
9118
9119 MachineInstr *MUL = MRI.getUniqueVRegDef(Root.getOperand(IdxMulOpd).getReg());
9120 Register ResultReg = Root.getOperand(0).getReg();
9121 Register SrcReg0 = MUL->getOperand(1).getReg();
9122 Register SrcReg1 = MUL->getOperand(2).getReg();
9123
9124 if (ResultReg.isVirtual())
9125 MRI.constrainRegClass(ResultReg, RC);
9126 if (SrcReg0.isVirtual())
9127 MRI.constrainRegClass(SrcReg0, RC);
9128 if (SrcReg1.isVirtual())
9129 MRI.constrainRegClass(SrcReg1, RC);
9131 MRI.constrainRegClass(VR, RC);
9132
9134 BuildMI(MF, MIMetadata(Root), TII->get(MaddOpc), ResultReg)
9135 .addReg(SrcReg0)
9136 .addReg(SrcReg1)
9137 .addReg(VR);
9138 // Insert the MADD
9139 InsInstrs.push_back(MIB);
9140 return MUL;
9141}
9142
9143/// Do the following transformation
9144/// A - (B + C) ==> (A - B) - C
9145/// A - (B + C) ==> (A - C) - B
9147 const TargetInstrInfo *TII, MachineInstr &Root,
9150 unsigned IdxOpd1,
9151 DenseMap<Register, unsigned> &InstrIdxForVirtReg) {
9152 assert(IdxOpd1 == 1 || IdxOpd1 == 2);
9153 unsigned IdxOtherOpd = IdxOpd1 == 1 ? 2 : 1;
9154 MachineInstr *AddMI = MRI.getUniqueVRegDef(Root.getOperand(2).getReg());
9155
9156 Register ResultReg = Root.getOperand(0).getReg();
9157 Register RegA = Root.getOperand(1).getReg();
9158 Register RegB = AddMI->getOperand(IdxOpd1).getReg();
9159 Register RegC = AddMI->getOperand(IdxOtherOpd).getReg();
9160 Register NewVR =
9161 MRI.createVirtualRegister(MRI.getRegClass(Root.getOperand(2).getReg()));
9162
9163 unsigned Opcode = Root.getOpcode();
9164 if (Opcode == AArch64::SUBSWrr)
9165 Opcode = AArch64::SUBWrr;
9166 else if (Opcode == AArch64::SUBSXrr)
9167 Opcode = AArch64::SUBXrr;
9168 else
9169 assert((Opcode == AArch64::SUBWrr || Opcode == AArch64::SUBXrr) &&
9170 "Unexpected instruction opcode.");
9171
9172 uint32_t Flags = Root.mergeFlagsWith(*AddMI);
9173 Flags &= ~MachineInstr::NoSWrap;
9174 Flags &= ~MachineInstr::NoUWrap;
9175
9176 MachineInstrBuilder MIB1 =
9177 BuildMI(MF, MIMetadata(Root), TII->get(Opcode), NewVR)
9178 .addReg(RegA)
9179 .addReg(RegB)
9180 .setMIFlags(Flags);
9181 MachineInstrBuilder MIB2 =
9182 BuildMI(MF, MIMetadata(Root), TII->get(Opcode), ResultReg)
9183 .addReg(NewVR)
9184 .addReg(RegC)
9185 .setMIFlags(Flags);
9186
9187 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9188 InsInstrs.push_back(MIB1);
9189 InsInstrs.push_back(MIB2);
9190 DelInstrs.push_back(AddMI);
9191 DelInstrs.push_back(&Root);
9192}
9193
9194unsigned AArch64InstrInfo::getReduceOpcodeForAccumulator(
9195 unsigned int AccumulatorOpCode) const {
9196 switch (AccumulatorOpCode) {
9197 case AArch64::UABALB_ZZZ_D:
9198 case AArch64::SABALB_ZZZ_D:
9199 case AArch64::UABALT_ZZZ_D:
9200 case AArch64::SABALT_ZZZ_D:
9201 return AArch64::ADD_ZZZ_D;
9202 case AArch64::UABALB_ZZZ_H:
9203 case AArch64::SABALB_ZZZ_H:
9204 case AArch64::UABALT_ZZZ_H:
9205 case AArch64::SABALT_ZZZ_H:
9206 return AArch64::ADD_ZZZ_H;
9207 case AArch64::UABALB_ZZZ_S:
9208 case AArch64::SABALB_ZZZ_S:
9209 case AArch64::UABALT_ZZZ_S:
9210 case AArch64::SABALT_ZZZ_S:
9211 return AArch64::ADD_ZZZ_S;
9212 case AArch64::UABALv16i8_v8i16:
9213 case AArch64::SABALv8i8_v8i16:
9214 case AArch64::SABAv8i16:
9215 case AArch64::UABAv8i16:
9216 return AArch64::ADDv8i16;
9217 case AArch64::SABALv2i32_v2i64:
9218 case AArch64::UABALv2i32_v2i64:
9219 case AArch64::SABALv4i32_v2i64:
9220 return AArch64::ADDv2i64;
9221 case AArch64::UABALv4i16_v4i32:
9222 case AArch64::SABALv4i16_v4i32:
9223 case AArch64::SABALv8i16_v4i32:
9224 case AArch64::SABAv4i32:
9225 case AArch64::UABAv4i32:
9226 return AArch64::ADDv4i32;
9227 case AArch64::UABALv4i32_v2i64:
9228 return AArch64::ADDv2i64;
9229 case AArch64::UABALv8i16_v4i32:
9230 return AArch64::ADDv4i32;
9231 case AArch64::UABALv8i8_v8i16:
9232 case AArch64::SABALv16i8_v8i16:
9233 return AArch64::ADDv8i16;
9234 case AArch64::UABAv16i8:
9235 case AArch64::SABAv16i8:
9236 return AArch64::ADDv16i8;
9237 case AArch64::UABAv4i16:
9238 case AArch64::SABAv4i16:
9239 return AArch64::ADDv4i16;
9240 case AArch64::UABAv2i32:
9241 case AArch64::SABAv2i32:
9242 return AArch64::ADDv2i32;
9243 case AArch64::UABAv8i8:
9244 case AArch64::SABAv8i8:
9245 return AArch64::ADDv8i8;
9246 default:
9247 llvm_unreachable("Unknown accumulator opcode");
9248 }
9249}
9250
9251/// When getMachineCombinerPatterns() finds potential patterns,
9252/// this function generates the instructions that could replace the
9253/// original code sequence
9254void AArch64InstrInfo::genAlternativeCodeSequence(
9255 MachineInstr &Root, unsigned Pattern,
9258 DenseMap<Register, unsigned> &InstrIdxForVirtReg) const {
9259 MachineBasicBlock &MBB = *Root.getParent();
9260 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
9261 MachineFunction &MF = *MBB.getParent();
9262 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
9263
9264 MachineInstr *MUL = nullptr;
9265 const TargetRegisterClass *RC;
9266 unsigned Opc;
9267 switch (Pattern) {
9268 default:
9269 // Reassociate instructions.
9270 TargetInstrInfo::genAlternativeCodeSequence(Root, Pattern, InsInstrs,
9271 DelInstrs, InstrIdxForVirtReg);
9272 return;
9274 // A - (B + C)
9275 // ==> (A - B) - C
9276 genSubAdd2SubSub(MF, MRI, TII, Root, InsInstrs, DelInstrs, 1,
9277 InstrIdxForVirtReg);
9278 return;
9280 // A - (B + C)
9281 // ==> (A - C) - B
9282 genSubAdd2SubSub(MF, MRI, TII, Root, InsInstrs, DelInstrs, 2,
9283 InstrIdxForVirtReg);
9284 return;
9287 // MUL I=A,B,0
9288 // ADD R,I,C
9289 // ==> MADD R,A,B,C
9290 // --- Create(MADD);
9292 Opc = AArch64::MADDWrrr;
9293 RC = &AArch64::GPR32RegClass;
9294 } else {
9295 Opc = AArch64::MADDXrrr;
9296 RC = &AArch64::GPR64RegClass;
9297 }
9298 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9299 break;
9302 // MUL I=A,B,0
9303 // ADD R,C,I
9304 // ==> MADD R,A,B,C
9305 // --- Create(MADD);
9307 Opc = AArch64::MADDWrrr;
9308 RC = &AArch64::GPR32RegClass;
9309 } else {
9310 Opc = AArch64::MADDXrrr;
9311 RC = &AArch64::GPR64RegClass;
9312 }
9313 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9314 break;
9319 // MUL I=A,B,0
9320 // ADD/SUB R,I,Imm
9321 // ==> MOV V, Imm/-Imm
9322 // ==> MADD R,A,B,V
9323 // --- Create(MADD);
9324 const TargetRegisterClass *RC;
9325 unsigned BitSize, MovImm;
9328 MovImm = AArch64::MOVi32imm;
9329 RC = &AArch64::GPR32spRegClass;
9330 BitSize = 32;
9331 Opc = AArch64::MADDWrrr;
9332 RC = &AArch64::GPR32RegClass;
9333 } else {
9334 MovImm = AArch64::MOVi64imm;
9335 RC = &AArch64::GPR64spRegClass;
9336 BitSize = 64;
9337 Opc = AArch64::MADDXrrr;
9338 RC = &AArch64::GPR64RegClass;
9339 }
9341 uint64_t Imm = Root.getOperand(2).getImm();
9342
9343 if (Root.getOperand(3).isImm()) {
9344 unsigned Val = Root.getOperand(3).getImm();
9345 Imm = Imm << Val;
9346 }
9347 bool IsSub = Pattern == AArch64MachineCombinerPattern::MULSUBWI_OP1 ||
9349 uint64_t UImm = SignExtend64(IsSub ? -Imm : Imm, BitSize);
9350 // Check that the immediate can be composed via a single instruction.
9352 AArch64_IMM::expandMOVImm(UImm, BitSize, Insn);
9353 if (Insn.size() != 1)
9354 return;
9355 MachineInstrBuilder MIB1 =
9356 BuildMI(MF, MIMetadata(Root), TII->get(MovImm), NewVR)
9357 .addImm(IsSub ? -Imm : Imm);
9358 InsInstrs.push_back(MIB1);
9359 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9360 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
9361 break;
9362 }
9365 // MUL I=A,B,0
9366 // SUB R,I, C
9367 // ==> SUB V, 0, C
9368 // ==> MADD R,A,B,V // = -C + A*B
9369 // --- Create(MADD);
9370 const TargetRegisterClass *SubRC;
9371 unsigned SubOpc, ZeroReg;
9373 SubOpc = AArch64::SUBWrr;
9374 SubRC = &AArch64::GPR32spRegClass;
9375 ZeroReg = AArch64::WZR;
9376 Opc = AArch64::MADDWrrr;
9377 RC = &AArch64::GPR32RegClass;
9378 } else {
9379 SubOpc = AArch64::SUBXrr;
9380 SubRC = &AArch64::GPR64spRegClass;
9381 ZeroReg = AArch64::XZR;
9382 Opc = AArch64::MADDXrrr;
9383 RC = &AArch64::GPR64RegClass;
9384 }
9385 Register NewVR = MRI.createVirtualRegister(SubRC);
9386 // SUB NewVR, 0, C
9387 MachineInstrBuilder MIB1 =
9388 BuildMI(MF, MIMetadata(Root), TII->get(SubOpc), NewVR)
9389 .addReg(ZeroReg)
9390 .add(Root.getOperand(2));
9391 InsInstrs.push_back(MIB1);
9392 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9393 MUL = genMaddR(MF, MRI, TII, Root, InsInstrs, 1, Opc, NewVR, RC);
9394 break;
9395 }
9398 // MUL I=A,B,0
9399 // SUB R,C,I
9400 // ==> MSUB R,A,B,C (computes C - A*B)
9401 // --- Create(MSUB);
9403 Opc = AArch64::MSUBWrrr;
9404 RC = &AArch64::GPR32RegClass;
9405 } else {
9406 Opc = AArch64::MSUBXrrr;
9407 RC = &AArch64::GPR64RegClass;
9408 }
9409 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9410 break;
9412 genMaddShf(MF, MRI, TII, Root, InsInstrs, DelInstrs, AArch64::MADDWrrr,
9413 false, InstrIdxForVirtReg);
9414 return;
9416 genMaddShf(MF, MRI, TII, Root, InsInstrs, DelInstrs, AArch64::MADDXrrr,
9417 true, InstrIdxForVirtReg);
9418 return;
9420 Opc = AArch64::MLAv8i8;
9421 RC = &AArch64::FPR64RegClass;
9422 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9423 break;
9425 Opc = AArch64::MLAv8i8;
9426 RC = &AArch64::FPR64RegClass;
9427 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9428 break;
9430 Opc = AArch64::MLAv16i8;
9431 RC = &AArch64::FPR128RegClass;
9432 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9433 break;
9435 Opc = AArch64::MLAv16i8;
9436 RC = &AArch64::FPR128RegClass;
9437 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9438 break;
9440 Opc = AArch64::MLAv4i16;
9441 RC = &AArch64::FPR64RegClass;
9442 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9443 break;
9445 Opc = AArch64::MLAv4i16;
9446 RC = &AArch64::FPR64RegClass;
9447 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9448 break;
9450 Opc = AArch64::MLAv8i16;
9451 RC = &AArch64::FPR128RegClass;
9452 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9453 break;
9455 Opc = AArch64::MLAv8i16;
9456 RC = &AArch64::FPR128RegClass;
9457 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9458 break;
9460 Opc = AArch64::MLAv2i32;
9461 RC = &AArch64::FPR64RegClass;
9462 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9463 break;
9465 Opc = AArch64::MLAv2i32;
9466 RC = &AArch64::FPR64RegClass;
9467 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9468 break;
9470 Opc = AArch64::MLAv4i32;
9471 RC = &AArch64::FPR128RegClass;
9472 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9473 break;
9475 Opc = AArch64::MLAv4i32;
9476 RC = &AArch64::FPR128RegClass;
9477 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9478 break;
9479
9481 Opc = AArch64::MLAv8i8;
9482 RC = &AArch64::FPR64RegClass;
9483 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9484 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i8,
9485 RC);
9486 break;
9488 Opc = AArch64::MLSv8i8;
9489 RC = &AArch64::FPR64RegClass;
9490 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9491 break;
9493 Opc = AArch64::MLAv16i8;
9494 RC = &AArch64::FPR128RegClass;
9495 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9496 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv16i8,
9497 RC);
9498 break;
9500 Opc = AArch64::MLSv16i8;
9501 RC = &AArch64::FPR128RegClass;
9502 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9503 break;
9505 Opc = AArch64::MLAv4i16;
9506 RC = &AArch64::FPR64RegClass;
9507 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9508 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i16,
9509 RC);
9510 break;
9512 Opc = AArch64::MLSv4i16;
9513 RC = &AArch64::FPR64RegClass;
9514 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9515 break;
9517 Opc = AArch64::MLAv8i16;
9518 RC = &AArch64::FPR128RegClass;
9519 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9520 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i16,
9521 RC);
9522 break;
9524 Opc = AArch64::MLSv8i16;
9525 RC = &AArch64::FPR128RegClass;
9526 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9527 break;
9529 Opc = AArch64::MLAv2i32;
9530 RC = &AArch64::FPR64RegClass;
9531 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9532 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv2i32,
9533 RC);
9534 break;
9536 Opc = AArch64::MLSv2i32;
9537 RC = &AArch64::FPR64RegClass;
9538 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9539 break;
9541 Opc = AArch64::MLAv4i32;
9542 RC = &AArch64::FPR128RegClass;
9543 MUL = genFusedMultiplyAccNeg(MF, MRI, TII, Root, InsInstrs,
9544 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i32,
9545 RC);
9546 break;
9548 Opc = AArch64::MLSv4i32;
9549 RC = &AArch64::FPR128RegClass;
9550 MUL = genFusedMultiplyAcc(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9551 break;
9552
9554 Opc = AArch64::MLAv4i16_indexed;
9555 RC = &AArch64::FPR64RegClass;
9556 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9557 break;
9559 Opc = AArch64::MLAv4i16_indexed;
9560 RC = &AArch64::FPR64RegClass;
9561 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9562 break;
9564 Opc = AArch64::MLAv8i16_indexed;
9565 RC = &AArch64::FPR128RegClass;
9566 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9567 break;
9569 Opc = AArch64::MLAv8i16_indexed;
9570 RC = &AArch64::FPR128RegClass;
9571 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9572 break;
9574 Opc = AArch64::MLAv2i32_indexed;
9575 RC = &AArch64::FPR64RegClass;
9576 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9577 break;
9579 Opc = AArch64::MLAv2i32_indexed;
9580 RC = &AArch64::FPR64RegClass;
9581 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9582 break;
9584 Opc = AArch64::MLAv4i32_indexed;
9585 RC = &AArch64::FPR128RegClass;
9586 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9587 break;
9589 Opc = AArch64::MLAv4i32_indexed;
9590 RC = &AArch64::FPR128RegClass;
9591 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9592 break;
9593
9595 Opc = AArch64::MLAv4i16_indexed;
9596 RC = &AArch64::FPR64RegClass;
9597 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9598 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i16,
9599 RC);
9600 break;
9602 Opc = AArch64::MLSv4i16_indexed;
9603 RC = &AArch64::FPR64RegClass;
9604 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9605 break;
9607 Opc = AArch64::MLAv8i16_indexed;
9608 RC = &AArch64::FPR128RegClass;
9609 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9610 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv8i16,
9611 RC);
9612 break;
9614 Opc = AArch64::MLSv8i16_indexed;
9615 RC = &AArch64::FPR128RegClass;
9616 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9617 break;
9619 Opc = AArch64::MLAv2i32_indexed;
9620 RC = &AArch64::FPR64RegClass;
9621 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9622 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv2i32,
9623 RC);
9624 break;
9626 Opc = AArch64::MLSv2i32_indexed;
9627 RC = &AArch64::FPR64RegClass;
9628 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9629 break;
9631 Opc = AArch64::MLAv4i32_indexed;
9632 RC = &AArch64::FPR128RegClass;
9633 MUL = genFusedMultiplyIdxNeg(MF, MRI, TII, Root, InsInstrs,
9634 InstrIdxForVirtReg, 1, Opc, AArch64::NEGv4i32,
9635 RC);
9636 break;
9638 Opc = AArch64::MLSv4i32_indexed;
9639 RC = &AArch64::FPR128RegClass;
9640 MUL = genFusedMultiplyIdx(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9641 break;
9642
9643 // Floating Point Support
9645 Opc = AArch64::FMADDHrrr;
9646 RC = &AArch64::FPR16RegClass;
9647 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9648 break;
9650 Opc = AArch64::FMADDSrrr;
9651 RC = &AArch64::FPR32RegClass;
9652 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9653 break;
9655 Opc = AArch64::FMADDDrrr;
9656 RC = &AArch64::FPR64RegClass;
9657 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9658 break;
9659
9661 Opc = AArch64::FMADDHrrr;
9662 RC = &AArch64::FPR16RegClass;
9663 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9664 break;
9666 Opc = AArch64::FMADDSrrr;
9667 RC = &AArch64::FPR32RegClass;
9668 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9669 break;
9671 Opc = AArch64::FMADDDrrr;
9672 RC = &AArch64::FPR64RegClass;
9673 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9674 break;
9675
9677 Opc = AArch64::FMLAv1i32_indexed;
9678 RC = &AArch64::FPR32RegClass;
9679 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9681 break;
9683 Opc = AArch64::FMLAv1i32_indexed;
9684 RC = &AArch64::FPR32RegClass;
9685 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9687 break;
9688
9690 Opc = AArch64::FMLAv1i64_indexed;
9691 RC = &AArch64::FPR64RegClass;
9692 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9694 break;
9696 Opc = AArch64::FMLAv1i64_indexed;
9697 RC = &AArch64::FPR64RegClass;
9698 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9700 break;
9701
9703 RC = &AArch64::FPR64RegClass;
9704 Opc = AArch64::FMLAv4i16_indexed;
9705 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9707 break;
9709 RC = &AArch64::FPR64RegClass;
9710 Opc = AArch64::FMLAv4f16;
9711 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9713 break;
9715 RC = &AArch64::FPR64RegClass;
9716 Opc = AArch64::FMLAv4i16_indexed;
9717 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9719 break;
9721 RC = &AArch64::FPR64RegClass;
9722 Opc = AArch64::FMLAv4f16;
9723 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9725 break;
9726
9729 RC = &AArch64::FPR64RegClass;
9731 Opc = AArch64::FMLAv2i32_indexed;
9732 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9734 } else {
9735 Opc = AArch64::FMLAv2f32;
9736 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9738 }
9739 break;
9742 RC = &AArch64::FPR64RegClass;
9744 Opc = AArch64::FMLAv2i32_indexed;
9745 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9747 } else {
9748 Opc = AArch64::FMLAv2f32;
9749 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9751 }
9752 break;
9753
9755 RC = &AArch64::FPR128RegClass;
9756 Opc = AArch64::FMLAv8i16_indexed;
9757 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9759 break;
9761 RC = &AArch64::FPR128RegClass;
9762 Opc = AArch64::FMLAv8f16;
9763 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9765 break;
9767 RC = &AArch64::FPR128RegClass;
9768 Opc = AArch64::FMLAv8i16_indexed;
9769 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9771 break;
9773 RC = &AArch64::FPR128RegClass;
9774 Opc = AArch64::FMLAv8f16;
9775 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9777 break;
9778
9781 RC = &AArch64::FPR128RegClass;
9783 Opc = AArch64::FMLAv2i64_indexed;
9784 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9786 } else {
9787 Opc = AArch64::FMLAv2f64;
9788 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9790 }
9791 break;
9794 RC = &AArch64::FPR128RegClass;
9796 Opc = AArch64::FMLAv2i64_indexed;
9797 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9799 } else {
9800 Opc = AArch64::FMLAv2f64;
9801 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9803 }
9804 break;
9805
9808 RC = &AArch64::FPR128RegClass;
9810 Opc = AArch64::FMLAv4i32_indexed;
9811 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9813 } else {
9814 Opc = AArch64::FMLAv4f32;
9815 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9817 }
9818 break;
9819
9822 RC = &AArch64::FPR128RegClass;
9824 Opc = AArch64::FMLAv4i32_indexed;
9825 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9827 } else {
9828 Opc = AArch64::FMLAv4f32;
9829 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9831 }
9832 break;
9833
9835 Opc = AArch64::FNMSUBHrrr;
9836 RC = &AArch64::FPR16RegClass;
9837 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9838 break;
9840 Opc = AArch64::FNMSUBSrrr;
9841 RC = &AArch64::FPR32RegClass;
9842 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9843 break;
9845 Opc = AArch64::FNMSUBDrrr;
9846 RC = &AArch64::FPR64RegClass;
9847 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9848 break;
9849
9851 Opc = AArch64::FNMADDHrrr;
9852 RC = &AArch64::FPR16RegClass;
9853 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9854 break;
9856 Opc = AArch64::FNMADDSrrr;
9857 RC = &AArch64::FPR32RegClass;
9858 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9859 break;
9861 Opc = AArch64::FNMADDDrrr;
9862 RC = &AArch64::FPR64RegClass;
9863 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC);
9864 break;
9865
9867 Opc = AArch64::FMSUBHrrr;
9868 RC = &AArch64::FPR16RegClass;
9869 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9870 break;
9872 Opc = AArch64::FMSUBSrrr;
9873 RC = &AArch64::FPR32RegClass;
9874 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9875 break;
9877 Opc = AArch64::FMSUBDrrr;
9878 RC = &AArch64::FPR64RegClass;
9879 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC);
9880 break;
9881
9883 Opc = AArch64::FMLSv1i32_indexed;
9884 RC = &AArch64::FPR32RegClass;
9885 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9887 break;
9888
9890 Opc = AArch64::FMLSv1i64_indexed;
9891 RC = &AArch64::FPR64RegClass;
9892 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9894 break;
9895
9898 RC = &AArch64::FPR64RegClass;
9900 MachineInstrBuilder MIB1 =
9901 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv4f16), NewVR)
9902 .add(Root.getOperand(2));
9903 InsInstrs.push_back(MIB1);
9904 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9906 Opc = AArch64::FMLAv4f16;
9907 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9908 FMAInstKind::Accumulator, &NewVR);
9909 } else {
9910 Opc = AArch64::FMLAv4i16_indexed;
9911 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9912 FMAInstKind::Indexed, &NewVR);
9913 }
9914 break;
9915 }
9917 RC = &AArch64::FPR64RegClass;
9918 Opc = AArch64::FMLSv4f16;
9919 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9921 break;
9923 RC = &AArch64::FPR64RegClass;
9924 Opc = AArch64::FMLSv4i16_indexed;
9925 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9927 break;
9928
9931 RC = &AArch64::FPR64RegClass;
9933 Opc = AArch64::FMLSv2i32_indexed;
9934 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9936 } else {
9937 Opc = AArch64::FMLSv2f32;
9938 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9940 }
9941 break;
9942
9945 RC = &AArch64::FPR128RegClass;
9947 MachineInstrBuilder MIB1 =
9948 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv8f16), NewVR)
9949 .add(Root.getOperand(2));
9950 InsInstrs.push_back(MIB1);
9951 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
9953 Opc = AArch64::FMLAv8f16;
9954 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9955 FMAInstKind::Accumulator, &NewVR);
9956 } else {
9957 Opc = AArch64::FMLAv8i16_indexed;
9958 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
9959 FMAInstKind::Indexed, &NewVR);
9960 }
9961 break;
9962 }
9964 RC = &AArch64::FPR128RegClass;
9965 Opc = AArch64::FMLSv8f16;
9966 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9968 break;
9970 RC = &AArch64::FPR128RegClass;
9971 Opc = AArch64::FMLSv8i16_indexed;
9972 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9974 break;
9975
9978 RC = &AArch64::FPR128RegClass;
9980 Opc = AArch64::FMLSv2i64_indexed;
9981 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9983 } else {
9984 Opc = AArch64::FMLSv2f64;
9985 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9987 }
9988 break;
9989
9992 RC = &AArch64::FPR128RegClass;
9994 Opc = AArch64::FMLSv4i32_indexed;
9995 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
9997 } else {
9998 Opc = AArch64::FMLSv4f32;
9999 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 2, Opc, RC,
10001 }
10002 break;
10005 RC = &AArch64::FPR64RegClass;
10007 MachineInstrBuilder MIB1 =
10008 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv2f32), NewVR)
10009 .add(Root.getOperand(2));
10010 InsInstrs.push_back(MIB1);
10011 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
10013 Opc = AArch64::FMLAv2i32_indexed;
10014 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
10015 FMAInstKind::Indexed, &NewVR);
10016 } else {
10017 Opc = AArch64::FMLAv2f32;
10018 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
10019 FMAInstKind::Accumulator, &NewVR);
10020 }
10021 break;
10022 }
10025 RC = &AArch64::FPR128RegClass;
10027 MachineInstrBuilder MIB1 =
10028 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv4f32), NewVR)
10029 .add(Root.getOperand(2));
10030 InsInstrs.push_back(MIB1);
10031 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
10033 Opc = AArch64::FMLAv4i32_indexed;
10034 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
10035 FMAInstKind::Indexed, &NewVR);
10036 } else {
10037 Opc = AArch64::FMLAv4f32;
10038 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
10039 FMAInstKind::Accumulator, &NewVR);
10040 }
10041 break;
10042 }
10045 RC = &AArch64::FPR128RegClass;
10047 MachineInstrBuilder MIB1 =
10048 BuildMI(MF, MIMetadata(Root), TII->get(AArch64::FNEGv2f64), NewVR)
10049 .add(Root.getOperand(2));
10050 InsInstrs.push_back(MIB1);
10051 InstrIdxForVirtReg.insert(std::make_pair(NewVR, 0));
10053 Opc = AArch64::FMLAv2i64_indexed;
10054 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
10055 FMAInstKind::Indexed, &NewVR);
10056 } else {
10057 Opc = AArch64::FMLAv2f64;
10058 MUL = genFusedMultiply(MF, MRI, TII, Root, InsInstrs, 1, Opc, RC,
10059 FMAInstKind::Accumulator, &NewVR);
10060 }
10061 break;
10062 }
10065 unsigned IdxDupOp =
10067 : 2;
10068 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv2i32_indexed,
10069 &AArch64::FPR128RegClass, MRI);
10070 break;
10071 }
10074 unsigned IdxDupOp =
10076 : 2;
10077 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv2i64_indexed,
10078 &AArch64::FPR128RegClass, MRI);
10079 break;
10080 }
10083 unsigned IdxDupOp =
10085 : 2;
10086 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv4i16_indexed,
10087 &AArch64::FPR128_loRegClass, MRI);
10088 break;
10089 }
10092 unsigned IdxDupOp =
10094 : 2;
10095 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv4i32_indexed,
10096 &AArch64::FPR128RegClass, MRI);
10097 break;
10098 }
10101 unsigned IdxDupOp =
10103 : 2;
10104 genIndexedMultiply(Root, InsInstrs, IdxDupOp, AArch64::FMULv8i16_indexed,
10105 &AArch64::FPR128_loRegClass, MRI);
10106 break;
10107 }
10109 MUL = genFNegatedMAD(MF, MRI, TII, Root, InsInstrs);
10110 break;
10111 }
10113 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
10114 Pattern, 4);
10115 break;
10116 }
10118 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
10119 Pattern, 8);
10120 break;
10121 }
10123 generateGatherLanePattern(Root, InsInstrs, DelInstrs, InstrIdxForVirtReg,
10124 Pattern, 16);
10125 break;
10126 }
10127
10128 } // end switch (Pattern)
10129 // Record MUL and ADD/SUB for deletion
10130 if (MUL)
10131 DelInstrs.push_back(MUL);
10132 DelInstrs.push_back(&Root);
10133
10134 // Set the flags on the inserted instructions to be the merged flags of the
10135 // instructions that we have combined.
10136 uint32_t Flags = Root.getFlags();
10137 if (MUL)
10138 Flags = Root.mergeFlagsWith(*MUL);
10139 for (auto *MI : InsInstrs)
10140 MI->setFlags(Flags);
10141}
10142
10143/// Replace csincr-branch sequence by simple conditional branch
10144///
10145/// Examples:
10146/// 1. \code
10147/// csinc w9, wzr, wzr, <condition code>
10148/// tbnz w9, #0, 0x44
10149/// \endcode
10150/// to
10151/// \code
10152/// b.<inverted condition code>
10153/// \endcode
10154///
10155/// 2. \code
10156/// csinc w9, wzr, wzr, <condition code>
10157/// tbz w9, #0, 0x44
10158/// \endcode
10159/// to
10160/// \code
10161/// b.<condition code>
10162/// \endcode
10163///
10164/// Replace compare and branch sequence by TBZ/TBNZ instruction when the
10165/// compare's constant operand is power of 2.
10166///
10167/// Examples:
10168/// \code
10169/// and w8, w8, #0x400
10170/// cbnz w8, L1
10171/// \endcode
10172/// to
10173/// \code
10174/// tbnz w8, #10, L1
10175/// \endcode
10176///
10177/// \param MI Conditional Branch
10178/// \return True when the simple conditional branch is generated
10179///
10181 bool IsNegativeBranch = false;
10182 bool IsTestAndBranch = false;
10183 unsigned TargetBBInMI = 0;
10184 switch (MI.getOpcode()) {
10185 default:
10186 llvm_unreachable("Unknown branch instruction?");
10187 case AArch64::Bcc:
10188 case AArch64::CBWPri:
10189 case AArch64::CBXPri:
10190 case AArch64::CBBAssertExt:
10191 case AArch64::CBHAssertExt:
10192 case AArch64::CBWPrr:
10193 case AArch64::CBXPrr:
10194 return false;
10195 case AArch64::CBZW:
10196 case AArch64::CBZX:
10197 TargetBBInMI = 1;
10198 break;
10199 case AArch64::CBNZW:
10200 case AArch64::CBNZX:
10201 TargetBBInMI = 1;
10202 IsNegativeBranch = true;
10203 break;
10204 case AArch64::TBZW:
10205 case AArch64::TBZX:
10206 TargetBBInMI = 2;
10207 IsTestAndBranch = true;
10208 break;
10209 case AArch64::TBNZW:
10210 case AArch64::TBNZX:
10211 TargetBBInMI = 2;
10212 IsNegativeBranch = true;
10213 IsTestAndBranch = true;
10214 break;
10215 }
10216 // So we increment a zero register and test for bits other
10217 // than bit 0? Conservatively bail out in case the verifier
10218 // missed this case.
10219 if (IsTestAndBranch && MI.getOperand(1).getImm())
10220 return false;
10221
10222 // Find Definition.
10223 assert(MI.getParent() && "Incomplete machine instruction\n");
10224 MachineBasicBlock *MBB = MI.getParent();
10225 MachineFunction *MF = MBB->getParent();
10227 Register VReg = MI.getOperand(0).getReg();
10228 if (!VReg.isVirtual())
10229 return false;
10230
10231 MachineInstr *DefMI = MRI->getVRegDef(VReg);
10232 if (!DefMI)
10233 return false;
10234
10235 // Look through COPY instructions to find definition.
10236 while (DefMI->isCopy()) {
10237 Register CopyVReg = DefMI->getOperand(1).getReg();
10238 if (!CopyVReg.isVirtual())
10239 return false;
10240 if (!MRI->hasOneNonDBGUse(CopyVReg))
10241 return false;
10242 DefMI = MRI->getVRegDef(CopyVReg);
10243 if (!DefMI)
10244 return false;
10245 }
10246
10247 switch (DefMI->getOpcode()) {
10248 default:
10249 return false;
10250 // Fold AND into a TBZ/TBNZ if constant operand is power of 2.
10251 case AArch64::ANDWri:
10252 case AArch64::ANDXri: {
10253 if (IsTestAndBranch)
10254 return false;
10255 if (DefMI->getParent() != MBB)
10256 return false;
10257 if (!MRI->hasOneNonDBGUse(VReg))
10258 return false;
10259
10260 bool Is32Bit = (DefMI->getOpcode() == AArch64::ANDWri);
10261 uint64_t Mask = AArch64_AM::decodeLogicalImmediate(
10262 DefMI->getOperand(2).getImm(), Is32Bit ? 32 : 64);
10263 if (!isPowerOf2_64(Mask))
10264 return false;
10265
10266 MachineOperand &MO = DefMI->getOperand(1);
10267 Register NewReg = MO.getReg();
10268 if (!NewReg.isVirtual())
10269 return false;
10270
10271 if (!MRI->getVRegDef(NewReg))
10272 return false;
10273
10274 MachineBasicBlock &RefToMBB = *MBB;
10275 MachineBasicBlock *TBB = MI.getOperand(1).getMBB();
10276 DebugLoc DL = MI.getDebugLoc();
10277 unsigned Imm = Log2_64(Mask);
10278 unsigned Opc = (Imm < 32)
10279 ? (IsNegativeBranch ? AArch64::TBNZW : AArch64::TBZW)
10280 : (IsNegativeBranch ? AArch64::TBNZX : AArch64::TBZX);
10281 MachineInstr *NewMI = BuildMI(RefToMBB, MI, DL, get(Opc))
10282 .addReg(NewReg)
10283 .addImm(Imm)
10284 .addMBB(TBB);
10285 // Register lives on to the CBZ now.
10286 MO.setIsKill(false);
10287
10288 // For immediate smaller than 32, we need to use the 32-bit
10289 // variant (W) in all cases. Indeed the 64-bit variant does not
10290 // allow to encode them.
10291 // Therefore, if the input register is 64-bit, we need to take the
10292 // 32-bit sub-part.
10293 if (!Is32Bit && Imm < 32)
10294 NewMI->getOperand(0).setSubReg(AArch64::sub_32);
10295 MI.eraseFromParent();
10296 return true;
10297 }
10298 // Look for CSINC
10299 case AArch64::CSINCWr:
10300 case AArch64::CSINCXr: {
10301 if (!(DefMI->getOperand(1).getReg() == AArch64::WZR &&
10302 DefMI->getOperand(2).getReg() == AArch64::WZR) &&
10303 !(DefMI->getOperand(1).getReg() == AArch64::XZR &&
10304 DefMI->getOperand(2).getReg() == AArch64::XZR))
10305 return false;
10306
10307 if (DefMI->findRegisterDefOperandIdx(AArch64::NZCV, /*TRI=*/nullptr,
10308 true) != -1)
10309 return false;
10310
10311 AArch64CC::CondCode CC = (AArch64CC::CondCode)DefMI->getOperand(3).getImm();
10312 // Convert only when the condition code is not modified between
10313 // the CSINC and the branch. The CC may be used by other
10314 // instructions in between.
10316 return false;
10317 MachineBasicBlock &RefToMBB = *MBB;
10318 MachineBasicBlock *TBB = MI.getOperand(TargetBBInMI).getMBB();
10319 DebugLoc DL = MI.getDebugLoc();
10320 if (IsNegativeBranch)
10322 BuildMI(RefToMBB, MI, DL, get(AArch64::Bcc)).addImm(CC).addMBB(TBB);
10323 MI.eraseFromParent();
10324 return true;
10325 }
10326 }
10327}
10328
10329std::pair<unsigned, unsigned>
10330AArch64InstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
10331 const unsigned Mask = AArch64II::MO_FRAGMENT;
10332 return std::make_pair(TF & Mask, TF & ~Mask);
10333}
10334
10336AArch64InstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
10337 using namespace AArch64II;
10338
10339 static const std::pair<unsigned, const char *> TargetFlags[] = {
10340 {MO_PAGE, "aarch64-page"}, {MO_PAGEOFF, "aarch64-pageoff"},
10341 {MO_G3, "aarch64-g3"}, {MO_G2, "aarch64-g2"},
10342 {MO_G1, "aarch64-g1"}, {MO_G0, "aarch64-g0"},
10343 {MO_HI12, "aarch64-hi12"}};
10344 return ArrayRef(TargetFlags);
10345}
10346
10348AArch64InstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const {
10349 using namespace AArch64II;
10350
10351 static const std::pair<unsigned, const char *> TargetFlags[] = {
10352 {MO_COFFSTUB, "aarch64-coffstub"},
10353 {MO_GOT, "aarch64-got"},
10354 {MO_NC, "aarch64-nc"},
10355 {MO_S, "aarch64-s"},
10356 {MO_TLS, "aarch64-tls"},
10357 {MO_DLLIMPORT, "aarch64-dllimport"},
10358 {MO_PREL, "aarch64-prel"},
10359 {MO_TAGGED, "aarch64-tagged"},
10360 {MO_ARM64EC_CALLMANGLE, "aarch64-arm64ec-callmangle"},
10361 };
10362 return ArrayRef(TargetFlags);
10363}
10364
10366AArch64InstrInfo::getSerializableMachineMemOperandTargetFlags() const {
10367 static const std::pair<MachineMemOperand::Flags, const char *> TargetFlags[] =
10368 {{MOSuppressPair, "aarch64-suppress-pair"},
10369 {MOStridedAccess, "aarch64-strided-access"}};
10370 return ArrayRef(TargetFlags);
10371}
10372
10373/// Constants defining how certain sequences should be outlined.
10374/// This encompasses how an outlined function should be called, and what kind of
10375/// frame should be emitted for that outlined function.
10376///
10377/// \p MachineOutlinerDefault implies that the function should be called with
10378/// a save and restore of LR to the stack.
10379///
10380/// That is,
10381///
10382/// I1 Save LR OUTLINED_FUNCTION:
10383/// I2 --> BL OUTLINED_FUNCTION I1
10384/// I3 Restore LR I2
10385/// I3
10386/// RET
10387///
10388/// * Call construction overhead: 3 (save + BL + restore)
10389/// * Frame construction overhead: 1 (ret)
10390/// * Requires stack fixups? Yes
10391///
10392/// \p MachineOutlinerTailCall implies that the function is being created from
10393/// a sequence of instructions ending in a return.
10394///
10395/// That is,
10396///
10397/// I1 OUTLINED_FUNCTION:
10398/// I2 --> B OUTLINED_FUNCTION I1
10399/// RET I2
10400/// RET
10401///
10402/// * Call construction overhead: 1 (B)
10403/// * Frame construction overhead: 0 (Return included in sequence)
10404/// * Requires stack fixups? No
10405///
10406/// \p MachineOutlinerNoLRSave implies that the function should be called using
10407/// a BL instruction, but doesn't require LR to be saved and restored. This
10408/// happens when LR is known to be dead.
10409///
10410/// That is,
10411///
10412/// I1 OUTLINED_FUNCTION:
10413/// I2 --> BL OUTLINED_FUNCTION I1
10414/// I3 I2
10415/// I3
10416/// RET
10417///
10418/// * Call construction overhead: 1 (BL)
10419/// * Frame construction overhead: 1 (RET)
10420/// * Requires stack fixups? No
10421///
10422/// \p MachineOutlinerThunk implies that the function is being created from
10423/// a sequence of instructions ending in a call. The outlined function is
10424/// called with a BL instruction, and the outlined function tail-calls the
10425/// original call destination.
10426///
10427/// That is,
10428///
10429/// I1 OUTLINED_FUNCTION:
10430/// I2 --> BL OUTLINED_FUNCTION I1
10431/// BL f I2
10432/// B f
10433/// * Call construction overhead: 1 (BL)
10434/// * Frame construction overhead: 0
10435/// * Requires stack fixups? No
10436///
10437/// \p MachineOutlinerRegSave implies that the function should be called with a
10438/// save and restore of LR to an available register. This allows us to avoid
10439/// stack fixups. Note that this outlining variant is compatible with the
10440/// NoLRSave case.
10441///
10442/// That is,
10443///
10444/// I1 Save LR OUTLINED_FUNCTION:
10445/// I2 --> BL OUTLINED_FUNCTION I1
10446/// I3 Restore LR I2
10447/// I3
10448/// RET
10449///
10450/// * Call construction overhead: 3 (save + BL + restore)
10451/// * Frame construction overhead: 1 (ret)
10452/// * Requires stack fixups? No
10454 MachineOutlinerDefault, /// Emit a save, restore, call, and return.
10455 MachineOutlinerTailCall, /// Only emit a branch.
10456 MachineOutlinerNoLRSave, /// Emit a call and return.
10457 MachineOutlinerThunk, /// Emit a call and tail-call.
10458 MachineOutlinerRegSave /// Same as default, but save to a register.
10459};
10460
10466
10467/// Return true if the frame-record form of the outlined prologue is enabled for
10468/// the target of \p MF.
10469///
10470/// A non-leaf outlined function must save LR. On MachO, saving LR alone
10471/// (str x30) has no compact unwind encoding, so we get a large DWARF FDE
10472/// instead. Saving FP and LR as a frame record (stp x29, x30 ; mov x29, sp)
10473/// gets the small FRAME encoding, and costs one extra instruction.
10475 return MF.getSubtarget<AArch64Subtarget>()
10476 .getCLOpts()
10477 .outliner_compact_unwind_frame &&
10479}
10480
10481/// Return true if the outlined function in \p MBB should save FP and LR as a
10482/// frame record instead of saving LR alone.
10484 const MachineBasicBlock &MBB) {
10485 const MachineFunction &MF = *MBB.getParent();
10486
10487 // Only worth it if the function has unwind info to shrink.
10490 return false;
10491
10492 // Only safe if the outlined code never touches FP, since we overwrite it.
10494 for (const MachineInstr &MI : MBB.instrs())
10495 LRU.accumulate(MI);
10496 return LRU.available(AArch64::FP);
10497}
10498
10499/// Predict what the above will answer, for use while costing candidates. The
10500/// outlined function does not exist yet, so answer from \p RepeatedSequenceLocs
10501/// instead. This is only an estimate; buildOutlinedFrame() makes the call.
10503 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
10504 const TargetRegisterInfo &TRI) {
10505 if (!isCompactUnwindFrameRecordEnabled(*RepeatedSequenceLocs.front().getMF()))
10506 return false;
10507
10508 // The outlined function is nounwind only if every candidate is, so it has
10509 // unwind info if any candidate does.
10510 if (llvm::none_of(RepeatedSequenceLocs, [](outliner::Candidate &C) {
10511 const MachineFunction &MF = *C.getMF();
10512 return MF.getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF);
10513 }))
10514 return false;
10515
10516 // FP is free in the outlined function only if it is free in every candidate.
10517 return llvm::all_of(RepeatedSequenceLocs, [&TRI](outliner::Candidate &C) {
10518 return C.isAvailableInsideSeq(AArch64::FP, TRI);
10519 });
10520}
10521
10523AArch64InstrInfo::findRegisterToSaveLRTo(outliner::Candidate &C) const {
10524 MachineFunction *MF = C.getMF();
10525 const TargetRegisterInfo &TRI = *MF->getSubtarget().getRegisterInfo();
10526 const AArch64RegisterInfo *ARI =
10527 static_cast<const AArch64RegisterInfo *>(&TRI);
10528 // Check if there is an available register across the sequence that we can
10529 // use.
10530 for (unsigned Reg : AArch64::GPR64RegClass) {
10531 if (!ARI->isReservedReg(*MF, Reg) &&
10532 Reg != AArch64::LR && // LR is not reserved, but don't use it.
10533 Reg != AArch64::X16 && // X16 is not guaranteed to be preserved.
10534 Reg != AArch64::X17 && // Ditto for X17.
10535 C.isAvailableAcrossAndOutOfSeq(Reg, TRI) &&
10536 C.isAvailableInsideSeq(Reg, TRI))
10537 return Reg;
10538 }
10539 return Register();
10540}
10541
10542static bool
10544 const outliner::Candidate &b) {
10545 const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>();
10546 const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>();
10547
10548 return MFIa->getSignReturnAddressCondition() ==
10550}
10551
10552static bool
10554 const outliner::Candidate &b) {
10555 const auto &MFIa = a.getMF()->getInfo<AArch64FunctionInfo>();
10556 const auto &MFIb = b.getMF()->getInfo<AArch64FunctionInfo>();
10557
10558 return MFIa->shouldSignWithBKey() == MFIb->shouldSignWithBKey();
10559}
10560
10562 const outliner::Candidate &b) {
10563 const AArch64Subtarget &SubtargetA =
10565 const AArch64Subtarget &SubtargetB =
10566 b.getMF()->getSubtarget<AArch64Subtarget>();
10567 return SubtargetA.hasV8_3aOps() == SubtargetB.hasV8_3aOps();
10568}
10569
10570std::optional<std::unique_ptr<outliner::OutlinedFunction>>
10571AArch64InstrInfo::getOutliningCandidateInfo(
10572 const MachineModuleInfo &MMI,
10573 std::vector<outliner::Candidate> &RepeatedSequenceLocs,
10574 unsigned MinRepeats) const {
10575 unsigned SequenceSize = 0;
10576 for (auto &MI : RepeatedSequenceLocs[0])
10577 SequenceSize += getInstSizeInBytes(MI);
10578
10579 unsigned NumBytesToCreateFrame = 0;
10580
10581 // Avoid splitting ADRP ADD/LDR pair into outlined functions.
10582 // These instructions are fused together by the scheduler.
10583 // Any candidate where ADRP is the last instruction should be rejected
10584 // as that will lead to splitting ADRP pair.
10585 MachineInstr &LastMI = RepeatedSequenceLocs[0].back();
10586 MachineInstr &FirstMI = RepeatedSequenceLocs[0].front();
10587 if (LastMI.getOpcode() == AArch64::ADRP &&
10588 (LastMI.getOperand(1).getTargetFlags() & AArch64II::MO_PAGE) != 0 &&
10589 (LastMI.getOperand(1).getTargetFlags() & AArch64II::MO_GOT) != 0) {
10590 return std::nullopt;
10591 }
10592
10593 // Similarly any candidate where the first instruction is ADD/LDR with a
10594 // page offset should be rejected to avoid ADRP splitting.
10595 if ((FirstMI.getOpcode() == AArch64::ADDXri ||
10596 FirstMI.getOpcode() == AArch64::LDRXui) &&
10597 (FirstMI.getOperand(2).getTargetFlags() & AArch64II::MO_PAGEOFF) != 0 &&
10598 (FirstMI.getOperand(2).getTargetFlags() & AArch64II::MO_GOT) != 0) {
10599 return std::nullopt;
10600 }
10601
10602 // We only allow outlining for functions having exactly matching return
10603 // address signing attributes, i.e., all share the same value for the
10604 // attribute "sign-return-address" and all share the same type of key they
10605 // are signed with.
10606 // Additionally we require all functions to simultaneously either support
10607 // v8.3a features or not. Otherwise an outlined function could get signed
10608 // using dedicated v8.3 instructions and a call from a function that doesn't
10609 // support v8.3 instructions would therefore be invalid.
10610 if (std::adjacent_find(
10611 RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(),
10612 [](const outliner::Candidate &a, const outliner::Candidate &b) {
10613 // Return true if a and b are non-equal w.r.t. return address
10614 // signing or support of v8.3a features
10615 if (outliningCandidatesSigningScopeConsensus(a, b) &&
10616 outliningCandidatesSigningKeyConsensus(a, b) &&
10617 outliningCandidatesV8_3OpsConsensus(a, b)) {
10618 return false;
10619 }
10620 return true;
10621 }) != RepeatedSequenceLocs.end()) {
10622 return std::nullopt;
10623 }
10624
10625 // Since at this point all candidates agree on their return address signing
10626 // picking just one is fine. If the candidate functions potentially sign their
10627 // return addresses, the outlined function should do the same. Note that in
10628 // the case of "sign-return-address"="non-leaf" this is an assumption: It is
10629 // not certainly true that the outlined function will have to sign its return
10630 // address but this decision is made later, when the decision to outline
10631 // has already been made.
10632 // The same holds for the number of additional instructions we need: On
10633 // v8.3a RET can be replaced by RETAA/RETAB and no AUT instruction is
10634 // necessary. However, at this point we don't know if the outlined function
10635 // will have a RET instruction so we assume the worst.
10636 const TargetRegisterInfo &TRI = getRegisterInfo();
10637 // Performing a tail call may require extra checks when PAuth is enabled.
10638 // If PAuth is disabled, set it to zero for uniformity.
10639 unsigned NumBytesToCheckLRInTCEpilogue = 0;
10640 const auto RASignCondition = RepeatedSequenceLocs[0]
10641 .getMF()
10642 ->getInfo<AArch64FunctionInfo>()
10643 ->getSignReturnAddressCondition();
10644 if (RASignCondition != SignReturnAddress::None) {
10645 // Candidates that have Return Address Authentication Hardening enabled are
10646 // discarded.
10647 //
10648 // In its current form, the machine outliner does not preserve X16/X17
10649 // across outlined function calls, even though it should as they are
10650 // caller-saved registers. And since the hardening based on load from the
10651 // return address may clobber one of these registers, if they are alive
10652 // across a call their value would be lost due to the hardening mechanism.
10653 llvm::erase_if(RepeatedSequenceLocs, [](outliner::Candidate &C) {
10654 return C.getMF()
10655 ->getInfo<AArch64FunctionInfo>()
10656 ->shouldHardenSignReturnAddress();
10657 });
10658 // If the sequence doesn't have enough candidates left, then we're done.
10659 if (RepeatedSequenceLocs.size() < MinRepeats)
10660 return std::nullopt;
10661
10662 // One PAC and one AUT instructions
10663 NumBytesToCreateFrame += 8;
10664
10665 // PAuth is enabled - set extra tail call cost, if any.
10666 auto LRCheckMethod = Subtarget.getAuthenticatedLRCheckMethod(
10667 *RepeatedSequenceLocs[0].getMF());
10668 NumBytesToCheckLRInTCEpilogue =
10670 // Checking the authenticated LR value may significantly impact
10671 // SequenceSize, so account for it for more precise results.
10672 if (isTailCallReturnInst(RepeatedSequenceLocs[0].back()))
10673 SequenceSize += NumBytesToCheckLRInTCEpilogue;
10674
10675 // We have to check if sp modifying instructions would get outlined.
10676 // If so we only allow outlining if sp is unchanged overall, so matching
10677 // sub and add instructions are okay to outline, all other sp modifications
10678 // are not
10679 auto hasIllegalSPModification = [&TRI](outliner::Candidate &C) {
10680 int SPValue = 0;
10681 for (auto &MI : C) {
10682 if (MI.modifiesRegister(AArch64::SP, &TRI)) {
10683 switch (MI.getOpcode()) {
10684 case AArch64::ADDXri:
10685 case AArch64::ADDWri:
10686 assert(MI.getNumOperands() == 4 && "Wrong number of operands");
10687 assert(MI.getOperand(2).isImm() &&
10688 "Expected operand to be immediate");
10689 assert(MI.getOperand(1).isReg() &&
10690 "Expected operand to be a register");
10691 // Check if the add just increments sp. If so, we search for
10692 // matching sub instructions that decrement sp. If not, the
10693 // modification is illegal
10694 if (MI.getOperand(1).getReg() == AArch64::SP)
10695 SPValue += MI.getOperand(2).getImm();
10696 else
10697 return true;
10698 break;
10699 case AArch64::SUBXri:
10700 case AArch64::SUBWri:
10701 assert(MI.getNumOperands() == 4 && "Wrong number of operands");
10702 assert(MI.getOperand(2).isImm() &&
10703 "Expected operand to be immediate");
10704 assert(MI.getOperand(1).isReg() &&
10705 "Expected operand to be a register");
10706 // Check if the sub just decrements sp. If so, we search for
10707 // matching add instructions that increment sp. If not, the
10708 // modification is illegal
10709 if (MI.getOperand(1).getReg() == AArch64::SP)
10710 SPValue -= MI.getOperand(2).getImm();
10711 else
10712 return true;
10713 break;
10714 default:
10715 return true;
10716 }
10717 }
10718 }
10719 if (SPValue)
10720 return true;
10721 return false;
10722 };
10723 // Remove candidates with illegal stack modifying instructions
10724 llvm::erase_if(RepeatedSequenceLocs, hasIllegalSPModification);
10725
10726 // If the sequence doesn't have enough candidates left, then we're done.
10727 if (RepeatedSequenceLocs.size() < MinRepeats)
10728 return std::nullopt;
10729 }
10730
10731 // Properties about candidate MBBs that hold for all of them.
10732 unsigned FlagsSetInAll = 0xF;
10733
10734 // Compute liveness information for each candidate, and set FlagsSetInAll.
10735 for (outliner::Candidate &C : RepeatedSequenceLocs)
10736 FlagsSetInAll &= C.Flags;
10737
10738 unsigned LastInstrOpcode = RepeatedSequenceLocs[0].back().getOpcode();
10739
10740 // Helper lambda which sets call information for every candidate.
10741 auto SetCandidateCallInfo =
10742 [&RepeatedSequenceLocs](unsigned CallID, unsigned NumBytesForCall) {
10743 for (outliner::Candidate &C : RepeatedSequenceLocs)
10744 C.setCallInfo(CallID, NumBytesForCall);
10745 };
10746
10747 unsigned FrameID = MachineOutlinerDefault;
10748 NumBytesToCreateFrame += 4;
10749
10750 bool HasBTI = any_of(RepeatedSequenceLocs, [](outliner::Candidate &C) {
10751 return C.getMF()->getInfo<AArch64FunctionInfo>()->branchTargetEnforcement();
10752 });
10753
10754 // We check to see if CFI Instructions are present, and if they are
10755 // we find the number of CFI Instructions in the candidates.
10756 unsigned CFICount = 0;
10757 for (auto &I : RepeatedSequenceLocs[0]) {
10758 if (I.isCFIInstruction())
10759 CFICount++;
10760 }
10761
10762 // We compare the number of found CFI Instructions to the number of CFI
10763 // instructions in the parent function for each candidate. We must check this
10764 // since if we outline one of the CFI instructions in a function, we have to
10765 // outline them all for correctness. If we do not, the address offsets will be
10766 // incorrect between the two sections of the program.
10767 for (outliner::Candidate &C : RepeatedSequenceLocs) {
10768 std::vector<MCCFIInstruction> CFIInstructions =
10769 C.getMF()->getFrameInstructions();
10770
10771 if (CFICount > 0 && CFICount != CFIInstructions.size())
10772 return std::nullopt;
10773 }
10774
10775 // Returns true if an instructions is safe to fix up, false otherwise.
10776 auto IsSafeToFixup = [this, &TRI](MachineInstr &MI) {
10777 if (MI.isCall())
10778 return true;
10779
10780 if (!MI.modifiesRegister(AArch64::SP, &TRI) &&
10781 !MI.readsRegister(AArch64::SP, &TRI))
10782 return true;
10783
10784 // Any modification of SP will break our code to save/restore LR.
10785 // FIXME: We could handle some instructions which add a constant
10786 // offset to SP, with a bit more work.
10787 if (MI.modifiesRegister(AArch64::SP, &TRI))
10788 return false;
10789
10790 // At this point, we have a stack instruction that we might need to
10791 // fix up. We'll handle it if it's a load or store.
10792 if (MI.mayLoadOrStore()) {
10793 const MachineOperand *Base; // Filled with the base operand of MI.
10794 int64_t Offset; // Filled with the offset of MI.
10795 bool OffsetIsScalable;
10796
10797 // Does it allow us to offset the base operand and is the base the
10798 // register SP?
10799 if (!getMemOperandWithOffset(MI, Base, Offset, OffsetIsScalable) ||
10800 !Base->isReg() || Base->getReg() != AArch64::SP)
10801 return false;
10802
10803 // Fixe-up code below assumes bytes.
10804 if (OffsetIsScalable)
10805 return false;
10806
10807 // Find the minimum/maximum offset for this instruction and check
10808 // if fixing it up would be in range.
10809 int64_t MinOffset,
10810 MaxOffset; // Unscaled offsets for the instruction.
10811 // The scale to multiply the offsets by.
10812 TypeSize Scale(0U, false), DummyWidth(0U, false);
10813 getMemOpInfo(MI.getOpcode(), Scale, DummyWidth, MinOffset, MaxOffset);
10814
10815 Offset += 16; // Update the offset to what it would be if we outlined.
10816 if (Offset < MinOffset * (int64_t)Scale.getFixedValue() ||
10817 Offset > MaxOffset * (int64_t)Scale.getFixedValue())
10818 return false;
10819
10820 // It's in range, so we can outline it.
10821 return true;
10822 }
10823
10824 // FIXME: Add handling for instructions like "add x0, sp, #8".
10825
10826 // We can't fix it up, so don't outline it.
10827 return false;
10828 };
10829
10830 // True if it's possible to fix up each stack instruction in this sequence.
10831 // Important for frames/call variants that modify the stack.
10832 bool AllStackInstrsSafe =
10833 llvm::all_of(RepeatedSequenceLocs[0], IsSafeToFixup);
10834
10835 // If the last instruction in any candidate is a terminator, then we should
10836 // tail call all of the candidates.
10837 if (RepeatedSequenceLocs[0].back().isTerminator()) {
10838 FrameID = MachineOutlinerTailCall;
10839 NumBytesToCreateFrame = 0;
10840 unsigned NumBytesForCall = 4 + NumBytesToCheckLRInTCEpilogue;
10841 SetCandidateCallInfo(MachineOutlinerTailCall, NumBytesForCall);
10842 }
10843
10844 else if (LastInstrOpcode == AArch64::BL ||
10845 ((LastInstrOpcode == AArch64::BLR ||
10846 LastInstrOpcode == AArch64::BLRNoIP) &&
10847 !HasBTI)) {
10848 // FIXME: Do we need to check if the code after this uses the value of LR?
10849 FrameID = MachineOutlinerThunk;
10850 NumBytesToCreateFrame = NumBytesToCheckLRInTCEpilogue;
10851 SetCandidateCallInfo(MachineOutlinerThunk, 4);
10852 }
10853
10854 else {
10855 // We need to decide how to emit calls + frames. We can always emit the same
10856 // frame if we don't need to save to the stack. If we have to save to the
10857 // stack, then we need a different frame.
10858 unsigned NumBytesNoStackCalls = 0;
10859 std::vector<outliner::Candidate> CandidatesWithoutStackFixups;
10860
10861 // Check if we have to save LR.
10862 for (outliner::Candidate &C : RepeatedSequenceLocs) {
10863 bool LRAvailable =
10865 ? C.isAvailableAcrossAndOutOfSeq(AArch64::LR, TRI)
10866 : true;
10867 // If we have a noreturn caller, then we're going to be conservative and
10868 // say that we have to save LR. If we don't have a ret at the end of the
10869 // block, then we can't reason about liveness accurately.
10870 //
10871 // FIXME: We can probably do better than always disabling this in
10872 // noreturn functions by fixing up the liveness info.
10873 bool IsNoReturn =
10874 C.getMF()->getFunction().hasFnAttribute(Attribute::NoReturn);
10875
10876 // Is LR available? If so, we don't need a save.
10877 if (LRAvailable && !IsNoReturn) {
10878 NumBytesNoStackCalls += 4;
10879 C.setCallInfo(MachineOutlinerNoLRSave, 4);
10880 CandidatesWithoutStackFixups.push_back(C);
10881 }
10882
10883 // Is an unused register available? If so, we won't modify the stack, so
10884 // we can outline with the same frame type as those that don't save LR.
10885 else if (findRegisterToSaveLRTo(C)) {
10886 NumBytesNoStackCalls += 12;
10887 C.setCallInfo(MachineOutlinerRegSave, 12);
10888 CandidatesWithoutStackFixups.push_back(C);
10889 }
10890
10891 // Is SP used in the sequence at all? If not, we don't have to modify
10892 // the stack, so we are guaranteed to get the same frame.
10893 else if (C.isAvailableInsideSeq(AArch64::SP, TRI)) {
10894 NumBytesNoStackCalls += 12;
10895 C.setCallInfo(MachineOutlinerDefault, 12);
10896 CandidatesWithoutStackFixups.push_back(C);
10897 }
10898
10899 // If we outline this, we need to modify the stack. Pretend we don't
10900 // outline this by saving all of its bytes.
10901 else {
10902 NumBytesNoStackCalls += SequenceSize;
10903 }
10904 }
10905
10906 // If there are no places where we have to save LR, then note that we
10907 // don't have to update the stack. Otherwise, give every candidate the
10908 // default call type, as long as it's safe to do so.
10909 if (!AllStackInstrsSafe ||
10910 NumBytesNoStackCalls <= RepeatedSequenceLocs.size() * 12) {
10911 RepeatedSequenceLocs = CandidatesWithoutStackFixups;
10912 FrameID = MachineOutlinerNoLRSave;
10913 if (RepeatedSequenceLocs.size() < MinRepeats)
10914 return std::nullopt;
10915 } else {
10916 SetCandidateCallInfo(MachineOutlinerDefault, 12);
10917
10918 // Bugzilla ID: 46767
10919 // TODO: Check if fixing up the stack more than once is safe so we can
10920 // outline these.
10921 //
10922 // An outline resulting in a caller that requires stack fixups at the
10923 // callsite to a callee that also requires stack fixups can happen when
10924 // there are no available registers at the candidate callsite for a
10925 // candidate that itself also has calls.
10926 //
10927 // In other words if function_containing_sequence in the following pseudo
10928 // assembly requires that we save LR at the point of the call, but there
10929 // are no available registers: in this case we save using SP and as a
10930 // result the SP offsets requires stack fixups by multiples of 16.
10931 //
10932 // function_containing_sequence:
10933 // ...
10934 // save LR to SP <- Requires stack instr fixups in OUTLINED_FUNCTION_N
10935 // call OUTLINED_FUNCTION_N
10936 // restore LR from SP
10937 // ...
10938 //
10939 // OUTLINED_FUNCTION_N:
10940 // save LR to SP <- Requires stack instr fixups in OUTLINED_FUNCTION_N
10941 // ...
10942 // bl foo
10943 // restore LR from SP
10944 // ret
10945 //
10946 // Because the code to handle more than one stack fixup does not
10947 // currently have the proper checks for legality, these cases will assert
10948 // in the AArch64 MachineOutliner. This is because the code to do this
10949 // needs more hardening, testing, better checks that generated code is
10950 // legal, etc and because it is only verified to handle a single pass of
10951 // stack fixup.
10952 //
10953 // The assert happens in AArch64InstrInfo::buildOutlinedFrame to catch
10954 // these cases until they are known to be handled. Bugzilla 46767 is
10955 // referenced in comments at the assert site.
10956 //
10957 // To avoid asserting (or generating non-legal code on noassert builds)
10958 // we remove all candidates which would need more than one stack fixup by
10959 // pruning the cases where the candidate has calls while also having no
10960 // available LR and having no available general purpose registers to copy
10961 // LR to (ie one extra stack save/restore).
10962 //
10963 if (FlagsSetInAll & MachineOutlinerMBBFlags::HasCalls) {
10964 erase_if(RepeatedSequenceLocs, [this, &TRI](outliner::Candidate &C) {
10965 auto IsCall = [](const MachineInstr &MI) { return MI.isCall(); };
10966 return (llvm::any_of(C, IsCall)) &&
10967 (!C.isAvailableAcrossAndOutOfSeq(AArch64::LR, TRI) ||
10968 !findRegisterToSaveLRTo(C));
10969 });
10970 }
10971 }
10972
10973 // If we dropped all of the candidates, bail out here.
10974 if (RepeatedSequenceLocs.size() < MinRepeats)
10975 return std::nullopt;
10976 }
10977
10978 // Does every candidate's MBB contain a call? If so, then we might have a call
10979 // in the range.
10980 if (FlagsSetInAll & MachineOutlinerMBBFlags::HasCalls) {
10981 // Check if the range contains a call. These require a save + restore of the
10982 // link register.
10983 outliner::Candidate &FirstCand = RepeatedSequenceLocs[0];
10984 bool ModStackToSaveLR = false;
10985 if (any_of(drop_end(FirstCand),
10986 [](const MachineInstr &MI) { return MI.isCall(); }))
10987 ModStackToSaveLR = true;
10988
10989 // Handle the last instruction separately. If this is a tail call, then the
10990 // last instruction is a call. We don't want to save + restore in this case.
10991 // However, it could be possible that the last instruction is a call without
10992 // it being valid to tail call this sequence. We should consider this as
10993 // well.
10994 else if (FrameID != MachineOutlinerThunk &&
10995 FrameID != MachineOutlinerTailCall && FirstCand.back().isCall())
10996 ModStackToSaveLR = true;
10997
10998 if (ModStackToSaveLR) {
10999 // We can't fix up the stack. Bail out.
11000 if (!AllStackInstrsSafe)
11001 return std::nullopt;
11002
11003 // Save + restore LR.
11004 NumBytesToCreateFrame += 8;
11005
11006 // Add the extra mov if we will save a frame record instead of just LR.
11008 RepeatedSequenceLocs, TRI))
11009 NumBytesToCreateFrame += 4;
11010 }
11011 }
11012
11013 // If we have CFI instructions, we can only outline if the outlined section
11014 // can be a tail call
11015 if (FrameID != MachineOutlinerTailCall && CFICount > 0)
11016 return std::nullopt;
11017
11018 return std::make_unique<outliner::OutlinedFunction>(
11019 RepeatedSequenceLocs, SequenceSize, NumBytesToCreateFrame, FrameID);
11020}
11021
11022void AArch64InstrInfo::mergeOutliningCandidateAttributes(
11023 Function &F, std::vector<outliner::Candidate> &Candidates) const {
11024 // If a bunch of candidates reach this point they must agree on their return
11025 // address signing. It is therefore enough to just consider the signing
11026 // behaviour of one of them
11027 const auto &CFn = Candidates.front().getMF()->getFunction();
11028
11029 if (CFn.hasFnAttribute("ptrauth-returns"))
11030 F.addFnAttr(CFn.getFnAttribute("ptrauth-returns"));
11031 if (CFn.hasFnAttribute("ptrauth-auth-traps"))
11032 F.addFnAttr(CFn.getFnAttribute("ptrauth-auth-traps"));
11033 // Since all candidates belong to the same module, just copy the
11034 // function-level attributes of an arbitrary function.
11035 if (CFn.hasFnAttribute("sign-return-address"))
11036 F.addFnAttr(CFn.getFnAttribute("sign-return-address"));
11037 if (CFn.hasFnAttribute("sign-return-address-key"))
11038 F.addFnAttr(CFn.getFnAttribute("sign-return-address-key"));
11039 // The "sign-return-address-harden" attribute is not included because no
11040 // candidate is supposed to have hardening enabled.
11041 assert(llvm::none_of(Candidates, [](const outliner::Candidate &C) {
11042 return C.getMF()
11043 ->getInfo<AArch64FunctionInfo>()
11044 ->shouldHardenSignReturnAddress();
11045 }));
11046
11047 AArch64GenInstrInfo::mergeOutliningCandidateAttributes(F, Candidates);
11048}
11049
11050bool AArch64InstrInfo::isFunctionSafeToOutlineFrom(
11051 MachineFunction &MF, bool OutlineFromLinkOnceODRs) const {
11053 OutlineFromLinkOnceODRs))
11054 return false;
11055
11056 // Outlining from functions with redzones is unsafe since the outliner may
11057 // modify the stack. Check if hasRedZone is true or unknown; if yes, don't
11058 // outline from it.
11059 AArch64FunctionInfo *AFI = MF.getInfo<AArch64FunctionInfo>();
11060 if (!AFI || AFI->hasRedZone().value_or(true))
11061 return false;
11062
11063 // FIXME: Determine whether it is safe to outline from functions which contain
11064 // streaming-mode changes. We may need to ensure any smstart/smstop pairs are
11065 // outlined together and ensure it is safe to outline with async unwind info,
11066 // required for saving & restoring VG around calls.
11067 if (AFI->hasStreamingModeChanges())
11068 return false;
11069
11070 // FIXME: Teach the outliner to generate/handle Windows unwind info.
11071 if (MF.usesWindowsUnwindInfo())
11072 return false;
11073
11074 // It's safe to outline from MF.
11075 return true;
11076}
11077
11079AArch64InstrInfo::getOutlinableRanges(MachineBasicBlock &MBB,
11080 unsigned &Flags) const {
11082 "Must track liveness!");
11084 std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
11085 Ranges;
11086 // According to the AArch64 Procedure Call Standard, the following are
11087 // undefined on entry/exit from a function call:
11088 //
11089 // * Registers x16, x17, (and thus w16, w17)
11090 // * Condition codes (and thus the NZCV register)
11091 //
11092 // If any of these registers are used inside or live across an outlined
11093 // function, then they may be modified later, either by the compiler or
11094 // some other tool (like the linker).
11095 //
11096 // To avoid outlining in these situations, partition each block into ranges
11097 // where these registers are dead. We will only outline from those ranges.
11098 LiveRegUnits LRU(getRegisterInfo());
11099 auto AreAllUnsafeRegsDead = [&LRU]() {
11100 return LRU.available(AArch64::W16) && LRU.available(AArch64::W17) &&
11101 LRU.available(AArch64::NZCV);
11102 };
11103
11104 // We need to know if LR is live across an outlining boundary later on in
11105 // order to decide how we'll create the outlined call, frame, etc.
11106 //
11107 // It's pretty expensive to check this for *every candidate* within a block.
11108 // That's some potentially n^2 behaviour, since in the worst case, we'd need
11109 // to compute liveness from the end of the block for O(n) candidates within
11110 // the block.
11111 //
11112 // So, to improve the average case, let's keep track of liveness from the end
11113 // of the block to the beginning of *every outlinable range*. If we know that
11114 // LR is available in every range we could outline from, then we know that
11115 // we don't need to check liveness for any candidate within that range.
11116 bool LRAvailableEverywhere = true;
11117 // Compute liveness bottom-up.
11118 LRU.addLiveOuts(MBB);
11119 // Update flags that require info about the entire MBB.
11120 auto UpdateWholeMBBFlags = [&Flags](const MachineInstr &MI) {
11121 if (MI.isCall() && !MI.isTerminator())
11123 };
11124 // Range: [RangeBegin, RangeEnd)
11125 MachineBasicBlock::instr_iterator RangeBegin, RangeEnd;
11126 unsigned RangeLen;
11127 auto CreateNewRangeStartingAt =
11128 [&RangeBegin, &RangeEnd,
11129 &RangeLen](MachineBasicBlock::instr_iterator NewBegin) {
11130 RangeBegin = NewBegin;
11131 RangeEnd = std::next(RangeBegin);
11132 RangeLen = 0;
11133 };
11134 auto SaveRangeIfNonEmpty = [&RangeLen, &Ranges, &RangeBegin, &RangeEnd]() {
11135 // At least one unsafe register is not dead. We do not want to outline at
11136 // this point. If it is long enough to outline from and does not cross a
11137 // bundle boundary, save the range [RangeBegin, RangeEnd).
11138 if (RangeLen <= 1)
11139 return;
11140 if (!RangeBegin.isEnd() && RangeBegin->isBundledWithPred())
11141 return;
11142 if (!RangeEnd.isEnd() && RangeEnd->isBundledWithPred())
11143 return;
11144 Ranges.emplace_back(RangeBegin, RangeEnd);
11145 };
11146 // Find the first point where all unsafe registers are dead.
11147 // FIND: <safe instr> <-- end of first potential range
11148 // SKIP: <unsafe def>
11149 // SKIP: ... everything between ...
11150 // SKIP: <unsafe use>
11151 auto FirstPossibleEndPt = MBB.instr_rbegin();
11152 for (; FirstPossibleEndPt != MBB.instr_rend(); ++FirstPossibleEndPt) {
11153 if (!FirstPossibleEndPt->isDebugInstr())
11154 LRU.stepBackward(*FirstPossibleEndPt);
11155 // Update flags that impact how we outline across the entire block,
11156 // regardless of safety.
11157 UpdateWholeMBBFlags(*FirstPossibleEndPt);
11158 if (AreAllUnsafeRegsDead())
11159 break;
11160 }
11161 // If we exhausted the entire block, we have no safe ranges to outline.
11162 if (FirstPossibleEndPt == MBB.instr_rend())
11163 return Ranges;
11164 // Current range.
11165 CreateNewRangeStartingAt(FirstPossibleEndPt->getIterator());
11166 // StartPt points to the first place where all unsafe registers
11167 // are dead (if there is any such point). Begin partitioning the MBB into
11168 // ranges.
11169 // Pseudo probes are ordinary instructions to the mapper, so only skip debug
11170 // instructions here.
11171 for (auto &MI : instructionsWithoutDebug(FirstPossibleEndPt, MBB.instr_rend(),
11172 /*SkipPseudoOp=*/false)) {
11173 LRU.stepBackward(MI);
11174 UpdateWholeMBBFlags(MI);
11175 if (!AreAllUnsafeRegsDead()) {
11176 SaveRangeIfNonEmpty();
11177 CreateNewRangeStartingAt(MI.getIterator());
11178 continue;
11179 }
11180 LRAvailableEverywhere &= LRU.available(AArch64::LR);
11181 // Pseudo probes count because the mapper treats them as ordinary
11182 // instructions.
11183 RangeBegin = MI.getIterator();
11184 ++RangeLen;
11185 }
11186 // Above loop misses the last (or only) range. If we are still safe, then
11187 // let's save the range.
11188 if (AreAllUnsafeRegsDead())
11189 SaveRangeIfNonEmpty();
11190 if (Ranges.empty())
11191 return Ranges;
11192 // We found the ranges bottom-up. Mapping expects the top-down. Reverse
11193 // the order.
11194 std::reverse(Ranges.begin(), Ranges.end());
11195 // If there is at least one outlinable range where LR is unavailable
11196 // somewhere, remember that.
11197 if (!LRAvailableEverywhere)
11199 return Ranges;
11200}
11201
11203AArch64InstrInfo::getOutliningTypeImpl(const MachineModuleInfo &MMI,
11205 unsigned Flags) const {
11206 MachineInstr &MI = *MIT;
11207
11208 // Don't outline anything used for return address signing. The outlined
11209 // function will get signed later if needed
11210 switch (MI.getOpcode()) {
11211 case AArch64::PACM:
11212 case AArch64::PACIASP:
11213 case AArch64::PACIBSP:
11214 case AArch64::PACIASPPC:
11215 case AArch64::PACIBSPPC:
11216 case AArch64::AUTIASP:
11217 case AArch64::AUTIBSP:
11218 case AArch64::AUTIASPPCi:
11219 case AArch64::AUTIASPPCr:
11220 case AArch64::AUTIBSPPCi:
11221 case AArch64::AUTIBSPPCr:
11222 case AArch64::RETAA:
11223 case AArch64::RETAB:
11224 case AArch64::RETAASPPCi:
11225 case AArch64::RETAASPPCr:
11226 case AArch64::RETABSPPCi:
11227 case AArch64::RETABSPPCr:
11228 case AArch64::EMITBKEY:
11229 case AArch64::PAUTH_PROLOGUE:
11230 case AArch64::PAUTH_EPILOGUE:
11231 case AArch64::PAUTH_EPILOGUE_ENTRY_SP:
11233 }
11234
11235 // We can only outline these if we will tail call the outlined function, or
11236 // fix up the CFI offsets. Currently, CFI instructions are outlined only if
11237 // in a tail call.
11238 //
11239 // FIXME: If the proper fixups for the offset are implemented, this should be
11240 // possible.
11241 if (MI.isCFIInstruction())
11243
11244 // Is this a terminator for a basic block?
11245 if (MI.isTerminator())
11246 // TargetInstrInfo::getOutliningType has already filtered out anything
11247 // that would break this, so we can allow it here.
11249
11250 // Make sure none of the operands are un-outlinable.
11251 for (const MachineOperand &MOP : MI.operands()) {
11252 // A check preventing CFI indices was here before, but only CFI
11253 // instructions should have those.
11254 assert(!MOP.isCFIIndex());
11255
11256 // If it uses LR or W30 explicitly, then don't touch it.
11257 if (MOP.isReg() && !MOP.isImplicit() &&
11258 (MOP.getReg() == AArch64::LR || MOP.getReg() == AArch64::W30))
11260 }
11261
11262 // Special cases for instructions that can always be outlined, but will fail
11263 // the later tests. e.g, ADRPs, which are PC-relative use LR, but can always
11264 // be outlined because they don't require a *specific* value to be in LR.
11265 if (MI.getOpcode() == AArch64::ADRP)
11267
11268 // If MI is a call we might be able to outline it. We don't want to outline
11269 // any calls that rely on the position of items on the stack. When we outline
11270 // something containing a call, we have to emit a save and restore of LR in
11271 // the outlined function. Currently, this always happens by saving LR to the
11272 // stack. Thus, if we outline, say, half the parameters for a function call
11273 // plus the call, then we'll break the callee's expectations for the layout
11274 // of the stack.
11275 //
11276 // FIXME: Allow calls to functions which construct a stack frame, as long
11277 // as they don't access arguments on the stack.
11278 // FIXME: Figure out some way to analyze functions defined in other modules.
11279 // We should be able to compute the memory usage based on the IR calling
11280 // convention, even if we can't see the definition.
11281 if (MI.isCall()) {
11282 // Get the function associated with the call. Look at each operand and find
11283 // the one that represents the callee and get its name.
11284 const Function *Callee = nullptr;
11285 for (const MachineOperand &MOP : MI.operands()) {
11286 if (MOP.isGlobal()) {
11287 Callee = dyn_cast<Function>(MOP.getGlobal());
11288 break;
11289 }
11290 }
11291
11292 // Never outline calls to mcount. There isn't any rule that would require
11293 // this, but the Linux kernel's "ftrace" feature depends on it.
11294 if (Callee && Callee->getName() == "\01_mcount")
11296
11297 // If we don't know anything about the callee, assume it depends on the
11298 // stack layout of the caller. In that case, it's only legal to outline
11299 // as a tail-call. Explicitly list the call instructions we know about so we
11300 // don't get unexpected results with call pseudo-instructions.
11301 auto UnknownCallOutlineType = outliner::InstrType::Illegal;
11302 if (MI.getOpcode() == AArch64::BLR ||
11303 MI.getOpcode() == AArch64::BLRNoIP || MI.getOpcode() == AArch64::BL)
11304 UnknownCallOutlineType = outliner::InstrType::LegalTerminator;
11305
11306 if (!Callee)
11307 return UnknownCallOutlineType;
11308
11309 // We have a function we have information about. Check it if it's something
11310 // can safely outline.
11311 MachineFunction *CalleeMF = MMI.getMachineFunction(*Callee);
11312
11313 // We don't know what's going on with the callee at all. Don't touch it.
11314 if (!CalleeMF)
11315 return UnknownCallOutlineType;
11316
11317 // Check if we know anything about the callee saves on the function. If we
11318 // don't, then don't touch it, since that implies that we haven't
11319 // computed anything about its stack frame yet.
11320 MachineFrameInfo &MFI = CalleeMF->getFrameInfo();
11321 if (!MFI.isCalleeSavedInfoValid() || MFI.getStackSize() > 0 ||
11322 MFI.getNumObjects() > 0)
11323 return UnknownCallOutlineType;
11324
11325 // At this point, we can say that CalleeMF ought to not pass anything on the
11326 // stack. Therefore, we can outline it.
11328 }
11329
11330 // Don't touch the link register or W30.
11331 if (MI.readsRegister(AArch64::W30, &getRegisterInfo()) ||
11332 MI.modifiesRegister(AArch64::W30, &getRegisterInfo()))
11334
11335 // Don't outline BTI instructions, because that will prevent the outlining
11336 // site from being indirectly callable.
11337 if (hasBTISemantics(MI))
11339
11341}
11342
11343void AArch64InstrInfo::fixupPostOutline(MachineBasicBlock &MBB) const {
11344 for (MachineInstr &MI : MBB) {
11345 const MachineOperand *Base;
11346 TypeSize Width(0, false);
11347 int64_t Offset;
11348 bool OffsetIsScalable;
11349
11350 // Is this a load or store with an immediate offset with SP as the base?
11351 if (!MI.mayLoadOrStore() ||
11352 !getMemOperandWithOffsetWidth(MI, Base, Offset, OffsetIsScalable,
11353 Width) ||
11354 (Base->isReg() && Base->getReg() != AArch64::SP))
11355 continue;
11356
11357 // It is, so we have to fix it up.
11358 TypeSize Scale(0U, false);
11359 int64_t Dummy1, Dummy2;
11360
11361 MachineOperand &StackOffsetOperand = getMemOpBaseRegImmOfsOffsetOperand(MI);
11362 assert(StackOffsetOperand.isImm() && "Stack offset wasn't immediate!");
11363 getMemOpInfo(MI.getOpcode(), Scale, Width, Dummy1, Dummy2);
11364 assert(Scale != 0 && "Unexpected opcode!");
11365 assert(!OffsetIsScalable && "Expected offset to be a byte offset");
11366
11367 // We've pushed the return address to the stack, so add 16 to the offset.
11368 // This is safe, since we already checked if it would overflow when we
11369 // checked if this instruction was legal to outline.
11370 int64_t NewImm = (Offset + 16) / (int64_t)Scale.getFixedValue();
11371 StackOffsetOperand.setImm(NewImm);
11372 }
11373}
11374
11376 const AArch64InstrInfo *TII,
11377 bool ShouldSignReturnAddr) {
11378 if (!ShouldSignReturnAddr)
11379 return;
11380
11381 BuildMI(MBB, MBB.begin(), DebugLoc(), TII->get(AArch64::PAUTH_PROLOGUE))
11383 TII->createPauthEpilogueInstr(MBB, DebugLoc());
11384}
11385
11386void AArch64InstrInfo::buildOutlinedFrame(
11388 const outliner::OutlinedFunction &OF) const {
11389
11390 AArch64FunctionInfo *FI = MF.getInfo<AArch64FunctionInfo>();
11391
11392 if (OF.FrameConstructionID == MachineOutlinerTailCall)
11393 FI->setOutliningStyle("Tail Call");
11394 else if (OF.FrameConstructionID == MachineOutlinerThunk) {
11395 // For thunk outlining, rewrite the last instruction from a call to a
11396 // tail-call.
11397 MachineInstr *Call = &*--MBB.instr_end();
11398 unsigned TailOpcode;
11399 if (Call->getOpcode() == AArch64::BL) {
11400 TailOpcode = AArch64::TCRETURNdi;
11401 } else {
11402 assert(Call->getOpcode() == AArch64::BLR ||
11403 Call->getOpcode() == AArch64::BLRNoIP);
11404 TailOpcode = AArch64::TCRETURNriALL;
11405 }
11406 MachineInstr *TC = BuildMI(MF, DebugLoc(), get(TailOpcode))
11407 .add(Call->getOperand(0))
11408 .addImm(0);
11409 MBB.insert(MBB.end(), TC);
11411
11412 FI->setOutliningStyle("Thunk");
11413 }
11414
11415 bool IsLeafFunction = true;
11416
11417 // Is there a call in the outlined range?
11418 auto IsNonTailCall = [](const MachineInstr &MI) {
11419 return MI.isCall() && !MI.isReturn();
11420 };
11421
11422 if (llvm::any_of(MBB.instrs(), IsNonTailCall)) {
11423 // Fix up the instructions in the range, since we're going to modify the
11424 // stack.
11425
11426 // Bugzilla ID: 46767
11427 // TODO: Check if fixing up twice is safe so we can outline these.
11428 assert(OF.FrameConstructionID != MachineOutlinerDefault &&
11429 "Can only fix up stack references once");
11430 fixupPostOutline(MBB);
11431
11432 IsLeafFunction = false;
11433
11434 // LR has to be a live in so that we can save it.
11435 if (!MBB.isLiveIn(AArch64::LR))
11436 MBB.addLiveIn(AArch64::LR);
11437
11440
11441 if (OF.FrameConstructionID == MachineOutlinerTailCall ||
11442 OF.FrameConstructionID == MachineOutlinerThunk)
11443 Et = std::prev(MBB.end());
11444
11445 // There is a call in the range, so we must save LR. Save it as part of a
11446 // frame record when that gives us a smaller compact unwind encoding.
11448 // FP is saved here, so it must be live-in.
11449 if (!MBB.isLiveIn(AArch64::FP))
11450 MBB.addLiveIn(AArch64::FP);
11451
11452 // stp x29, x30, [sp, #-16]! (the pre-index imm is scaled by 8: -2 * 8)
11453 MachineInstr *STPXpre = BuildMI(MF, DebugLoc(), get(AArch64::STPXpre))
11454 .addReg(AArch64::SP, RegState::Define)
11455 .addReg(AArch64::FP)
11456 .addReg(AArch64::LR)
11457 .addReg(AArch64::SP)
11458 .addImm(-2);
11459 It = MBB.insert(It, STPXpre);
11460
11461 // mov x29, sp (add x29, sp, #0), so x29 points at the frame record.
11462 MachineInstr *SetFP = BuildMI(MF, DebugLoc(), get(AArch64::ADDXri))
11463 .addReg(AArch64::FP, RegState::Define)
11464 .addReg(AArch64::SP)
11465 .addImm(0)
11466 .addImm(0);
11467 MBB.insertAfter(It, SetFP);
11468
11469 // Describe the frame record with FP as the CFA. The encoder needs all
11470 // three to pick FRAME. No need to check for unwind info here: we only
11471 // get here if the function has it.
11472 CFIInstBuilder CFIBuilder(MBB, std::next(SetFP->getIterator()),
11474 CFIBuilder.buildDefCFA(AArch64::FP, 16);
11475 CFIBuilder.buildOffset(AArch64::LR, -8);
11476 CFIBuilder.buildOffset(AArch64::FP, -16);
11477
11478 // ldp x29, x30, [sp], #16
11479 MachineInstr *LDPXpost = BuildMI(MF, DebugLoc(), get(AArch64::LDPXpost))
11480 .addReg(AArch64::SP, RegState::Define)
11481 .addReg(AArch64::FP, RegState::Define)
11482 .addReg(AArch64::LR, RegState::Define)
11483 .addReg(AArch64::SP)
11484 .addImm(2);
11485 Et = MBB.insert(Et, LDPXpost);
11486 } else {
11487 // Insert a save before the outlined region
11488 MachineInstr *STRXpre = BuildMI(MF, DebugLoc(), get(AArch64::STRXpre))
11489 .addReg(AArch64::SP, RegState::Define)
11490 .addReg(AArch64::LR)
11491 .addReg(AArch64::SP)
11492 .addImm(-16);
11493 It = MBB.insert(It, STRXpre);
11494
11495 if (MF.getInfo<AArch64FunctionInfo>()->needsDwarfUnwindInfo(MF)) {
11496 CFIInstBuilder CFIBuilder(MBB, It, MachineInstr::FrameSetup);
11497
11498 // Add a CFI saying the stack was moved 16 B down.
11499 CFIBuilder.buildDefCFAOffset(16);
11500
11501 // Add a CFI saying that the LR that we want to find is now 16 B higher
11502 // than before.
11503 CFIBuilder.buildOffset(AArch64::LR, -16);
11504 }
11505
11506 // Insert a restore before the terminator for the function.
11507 MachineInstr *LDRXpost = BuildMI(MF, DebugLoc(), get(AArch64::LDRXpost))
11508 .addReg(AArch64::SP, RegState::Define)
11509 .addReg(AArch64::LR, RegState::Define)
11510 .addReg(AArch64::SP)
11511 .addImm(16);
11512 Et = MBB.insert(Et, LDRXpost);
11513 }
11514 }
11515
11516 auto RASignCondition = FI->getSignReturnAddressCondition();
11517 bool ShouldSignReturnAddr = AArch64FunctionInfo::shouldSignReturnAddress(
11518 RASignCondition, !IsLeafFunction);
11519
11520 // If this is a tail call outlined function, then there's already a return.
11521 if (OF.FrameConstructionID == MachineOutlinerTailCall ||
11522 OF.FrameConstructionID == MachineOutlinerThunk) {
11523 signOutlinedFunction(MF, MBB, this, ShouldSignReturnAddr);
11524 return;
11525 }
11526
11527 // It's not a tail call, so we have to insert the return ourselves.
11528
11529 // LR has to be a live in so that we can return to it.
11530 if (!MBB.isLiveIn(AArch64::LR))
11531 MBB.addLiveIn(AArch64::LR);
11532
11533 MachineInstr *ret = BuildMI(MF, DebugLoc(), get(AArch64::RET))
11534 .addReg(AArch64::LR);
11535 MBB.insert(MBB.end(), ret);
11536
11537 signOutlinedFunction(MF, MBB, this, ShouldSignReturnAddr);
11538
11539 FI->setOutliningStyle("Function");
11540
11541 // Did we have to modify the stack by saving the link register?
11542 if (OF.FrameConstructionID != MachineOutlinerDefault)
11543 return;
11544
11545 // We modified the stack.
11546 // Walk over the basic block and fix up all the stack accesses.
11547 fixupPostOutline(MBB);
11548}
11549
11550MachineBasicBlock::iterator AArch64InstrInfo::insertOutlinedCall(
11553
11554 // Are we tail calling?
11555 if (C.CallConstructionID == MachineOutlinerTailCall) {
11556 // If yes, then we can just branch to the label.
11557 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::TCRETURNdi))
11558 .addGlobalAddress(M.getNamedValue(MF.getName()))
11559 .addImm(0));
11560 return It;
11561 }
11562
11563 // Are we saving the link register?
11564 if (C.CallConstructionID == MachineOutlinerNoLRSave ||
11565 C.CallConstructionID == MachineOutlinerThunk) {
11566 // No, so just insert the call.
11567 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::BL))
11568 .addGlobalAddress(M.getNamedValue(MF.getName())));
11569 return It;
11570 }
11571
11572 // We want to return the spot where we inserted the call.
11574
11575 // Instructions for saving and restoring LR around the call instruction we're
11576 // going to insert.
11577 MachineInstr *Save;
11578 MachineInstr *Restore;
11579 // Can we save to a register?
11580 if (C.CallConstructionID == MachineOutlinerRegSave) {
11581 // FIXME: This logic should be sunk into a target-specific interface so that
11582 // we don't have to recompute the register.
11583 Register Reg = findRegisterToSaveLRTo(C);
11584 assert(Reg && "No callee-saved register available?");
11585
11586 // LR has to be a live in so that we can save it.
11587 if (!MBB.isLiveIn(AArch64::LR))
11588 MBB.addLiveIn(AArch64::LR);
11589
11590 // Save and restore LR from Reg.
11591 Save = BuildMI(MF, DebugLoc(), get(AArch64::ORRXrs), Reg)
11592 .addReg(AArch64::XZR)
11593 .addReg(AArch64::LR)
11594 .addImm(0);
11595 Restore = BuildMI(MF, DebugLoc(), get(AArch64::ORRXrs), AArch64::LR)
11596 .addReg(AArch64::XZR)
11597 .addReg(Reg)
11598 .addImm(0);
11599 } else {
11600 // We have the default case. Save and restore from SP.
11601 Save = BuildMI(MF, DebugLoc(), get(AArch64::STRXpre))
11602 .addReg(AArch64::SP, RegState::Define)
11603 .addReg(AArch64::LR)
11604 .addReg(AArch64::SP)
11605 .addImm(-16);
11606 Restore = BuildMI(MF, DebugLoc(), get(AArch64::LDRXpost))
11607 .addReg(AArch64::SP, RegState::Define)
11608 .addReg(AArch64::LR, RegState::Define)
11609 .addReg(AArch64::SP)
11610 .addImm(16);
11611 }
11612
11613 It = MBB.insert(It, Save);
11614 It++;
11615
11616 // Insert the call.
11617 It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::BL))
11618 .addGlobalAddress(M.getNamedValue(MF.getName())));
11619 CallPt = It;
11620 It++;
11621
11622 It = MBB.insert(It, Restore);
11623 return CallPt;
11624}
11625
11626bool AArch64InstrInfo::shouldOutlineFromFunctionByDefault(
11627 MachineFunction &MF) const {
11628 return MF.getFunction().hasMinSize();
11629}
11630
11631void AArch64InstrInfo::buildClearRegister(Register Reg, MachineBasicBlock &MBB,
11633 DebugLoc &DL,
11634 bool AllowSideEffects) const {
11635 const MachineFunction &MF = *MBB.getParent();
11636 const AArch64Subtarget &STI = MF.getSubtarget<AArch64Subtarget>();
11637 const AArch64RegisterInfo &TRI = *STI.getRegisterInfo();
11638
11639 if (TRI.isGeneralPurposeRegister(MF, Reg)) {
11640 BuildMI(MBB, Iter, DL, get(AArch64::MOVZXi), Reg).addImm(0).addImm(0);
11641 } else if (STI.isSVEorStreamingSVEAvailable()) {
11642 BuildMI(MBB, Iter, DL, get(AArch64::DUP_ZI_D), Reg)
11643 .addImm(0)
11644 .addImm(0);
11645 } else if (STI.isNeonAvailable()) {
11646 BuildMI(MBB, Iter, DL, get(AArch64::MOVIv2d_ns), Reg)
11647 .addImm(0);
11648 } else {
11649 // No Advanced SIMD (streaming-compatible without SVE, or +nosimd), so use
11650 // `fmov d...` instead of `movi v...`; writing `d` also clears the upper
11651 // 64 bits.
11652 assert(STI.hasFPARMv8() && "Expected FP to be available.");
11653 Register Reg64 = TRI.getSubReg(Reg, AArch64::dsub);
11654 BuildMI(MBB, Iter, DL, get(AArch64::FMOVD0), Reg64);
11655 }
11656}
11657
11658std::optional<DestSourcePair>
11660
11661 // AArch64::ORRWrs and AArch64::ORRXrs with WZR/XZR reg
11662 // and zero immediate operands used as an alias for mov instruction.
11663 if ((MI.getOpcode() == AArch64::ORRWrs &&
11664 MI.getOperand(1).getReg() == AArch64::WZR &&
11665 MI.getOperand(3).getImm() == 0x0) ||
11666 (MI.getOpcode() == AArch64::ORRWrr &&
11667 MI.getOperand(1).getReg() == AArch64::WZR)) {
11668 // Check that the w->w move is not a zero-extending w->x mov.
11669 if ((MI.getOperand(0).getReg().isPhysical() &&
11670 MI.findRegisterDefOperandIdx(
11671 getXRegFromWReg(MI.getOperand(0).getReg()),
11672 /*TRI=*/nullptr) == -1) ||
11673 (MI.getOperand(0).getReg().isVirtual() &&
11674 !MI.getOperand(0).getSubReg()))
11675 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11676 }
11677
11678 if (MI.getOpcode() == AArch64::ORRXrs &&
11679 MI.getOperand(1).getReg() == AArch64::XZR &&
11680 MI.getOperand(3).getImm() == 0x0)
11681 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11682
11683 return std::nullopt;
11684}
11685
11686std::optional<DestSourcePair>
11688 if ((MI.getOpcode() == AArch64::ORRWrs &&
11689 MI.getOperand(1).getReg() == AArch64::WZR &&
11690 MI.getOperand(3).getImm() == 0x0) ||
11691 (MI.getOpcode() == AArch64::ORRWrr &&
11692 MI.getOperand(1).getReg() == AArch64::WZR))
11693 return DestSourcePair{MI.getOperand(0), MI.getOperand(2)};
11694 return std::nullopt;
11695}
11696
11697std::optional<RegImmPair>
11698AArch64InstrInfo::isAddImmediate(const MachineInstr &MI, Register Reg) const {
11699 int Sign = 1;
11700 int64_t Offset = 0;
11701
11702 // TODO: Handle cases where Reg is a super- or sub-register of the
11703 // destination register.
11704 const MachineOperand &Op0 = MI.getOperand(0);
11705 if (!Op0.isReg() || Reg != Op0.getReg())
11706 return std::nullopt;
11707
11708 switch (MI.getOpcode()) {
11709 default:
11710 return std::nullopt;
11711 case AArch64::SUBWri:
11712 case AArch64::SUBXri:
11713 case AArch64::SUBSWri:
11714 case AArch64::SUBSXri:
11715 Sign *= -1;
11716 [[fallthrough]];
11717 case AArch64::ADDSWri:
11718 case AArch64::ADDSXri:
11719 case AArch64::ADDWri:
11720 case AArch64::ADDXri: {
11721 // TODO: Third operand can be global address (usually some string).
11722 if (!MI.getOperand(0).isReg() || !MI.getOperand(1).isReg() ||
11723 !MI.getOperand(2).isImm())
11724 return std::nullopt;
11725 int Shift = MI.getOperand(3).getImm();
11726 assert((Shift == 0 || Shift == 12) && "Shift can be either 0 or 12");
11727 Offset = Sign * (MI.getOperand(2).getImm() << Shift);
11728 }
11729 }
11730 return RegImmPair{MI.getOperand(1).getReg(), Offset};
11731}
11732
11733/// If the given ORR instruction is a copy, and \p DescribedReg overlaps with
11734/// the destination register then, if possible, describe the value in terms of
11735/// the source register.
11736static std::optional<ParamLoadedValue>
11738 const TargetInstrInfo *TII,
11739 const TargetRegisterInfo *TRI) {
11740 auto DestSrc = TII->isCopyLikeInstr(MI);
11741 if (!DestSrc)
11742 return std::nullopt;
11743
11744 Register DestReg = DestSrc->Destination->getReg();
11745 Register SrcReg = DestSrc->Source->getReg();
11746
11747 if (!DestReg.isValid() || !SrcReg.isValid())
11748 return std::nullopt;
11749
11750 auto Expr = DIExpression::get(MI.getMF()->getFunction().getContext(), {});
11751
11752 // If the described register is the destination, just return the source.
11753 if (DestReg == DescribedReg)
11754 return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
11755
11756 // ORRWrs zero-extends to 64-bits, so we need to consider such cases.
11757 if (MI.getOpcode() == AArch64::ORRWrs &&
11758 TRI->isSuperRegister(DestReg, DescribedReg))
11759 return ParamLoadedValue(MachineOperand::CreateReg(SrcReg, false), Expr);
11760
11761 // We may need to describe the lower part of a ORRXrs move.
11762 if (MI.getOpcode() == AArch64::ORRXrs &&
11763 TRI->isSubRegister(DestReg, DescribedReg)) {
11764 Register SrcSubReg = TRI->getSubReg(SrcReg, AArch64::sub_32);
11765 return ParamLoadedValue(MachineOperand::CreateReg(SrcSubReg, false), Expr);
11766 }
11767
11768 assert(!TRI->isSuperOrSubRegisterEq(DestReg, DescribedReg) &&
11769 "Unhandled ORR[XW]rs copy case");
11770
11771 return std::nullopt;
11772}
11773
11774bool AArch64InstrInfo::isFunctionSafeToSplit(const MachineFunction &MF) const {
11775 // Functions cannot be split to different sections on AArch64 if they have
11776 // a red zone. This is because relaxing a cross-section branch may require
11777 // incrementing the stack pointer to spill a register, which would overwrite
11778 // the red zone.
11779 if (MF.getInfo<AArch64FunctionInfo>()->hasRedZone().value_or(true))
11780 return false;
11781
11783}
11784
11785bool AArch64InstrInfo::isMBBSafeToSplitToCold(
11786 const MachineBasicBlock &MBB) const {
11787 // Asm Goto blocks can contain conditional branches to goto labels, which can
11788 // get moved out of range of the branch instruction.
11789 auto isAsmGoto = [](const MachineInstr &MI) {
11790 return MI.getOpcode() == AArch64::INLINEASM_BR;
11791 };
11792 if (llvm::any_of(MBB, isAsmGoto) || MBB.isInlineAsmBrIndirectTarget())
11793 return false;
11794
11795 // Because jump tables are label-relative instead of table-relative, they all
11796 // must be in the same section or relocation fixup handling will fail.
11797
11798 // Check if MBB is a jump table target
11799 const MachineJumpTableInfo *MJTI = MBB.getParent()->getJumpTableInfo();
11800 auto containsMBB = [&MBB](const MachineJumpTableEntry &JTE) {
11801 return llvm::is_contained(JTE.MBBs, &MBB);
11802 };
11803 if (MJTI != nullptr && llvm::any_of(MJTI->getJumpTables(), containsMBB))
11804 return false;
11805
11806 // Check if MBB contains a jump table lookup
11807 for (const MachineInstr &MI : MBB) {
11808 switch (MI.getOpcode()) {
11809 case TargetOpcode::G_BRJT:
11810 case AArch64::JumpTableDest32:
11811 case AArch64::JumpTableDest16:
11812 case AArch64::JumpTableDest8:
11813 return false;
11814 default:
11815 continue;
11816 }
11817 }
11818
11819 // MBB isn't a special case, so it's safe to be split to the cold section.
11820 return true;
11821}
11822
11823std::optional<ParamLoadedValue>
11824AArch64InstrInfo::describeLoadedValue(const MachineInstr &MI,
11825 Register Reg) const {
11826 const MachineFunction *MF = MI.getMF();
11827 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
11828 switch (MI.getOpcode()) {
11829 case AArch64::MOVZWi:
11830 case AArch64::MOVZXi: {
11831 // MOVZWi may be used for producing zero-extended 32-bit immediates in
11832 // 64-bit parameters, so we need to consider super-registers.
11833 if (!TRI->isSuperRegisterEq(MI.getOperand(0).getReg(), Reg))
11834 return std::nullopt;
11835
11836 if (!MI.getOperand(1).isImm())
11837 return std::nullopt;
11838 int64_t Immediate = MI.getOperand(1).getImm();
11839 int Shift = MI.getOperand(2).getImm();
11840 return ParamLoadedValue(MachineOperand::CreateImm(Immediate << Shift),
11841 nullptr);
11842 }
11843 case AArch64::ORRWrs:
11844 case AArch64::ORRXrs:
11845 return describeORRLoadedValue(MI, Reg, this, TRI);
11846 }
11847
11849}
11850
11851bool AArch64InstrInfo::isExtendLikelyToBeFolded(
11852 MachineInstr &ExtMI, MachineRegisterInfo &MRI) const {
11853 assert(ExtMI.getOpcode() == TargetOpcode::G_SEXT ||
11854 ExtMI.getOpcode() == TargetOpcode::G_ZEXT ||
11855 ExtMI.getOpcode() == TargetOpcode::G_ANYEXT);
11856
11857 // Anyexts are nops.
11858 if (ExtMI.getOpcode() == TargetOpcode::G_ANYEXT)
11859 return true;
11860
11861 Register DefReg = ExtMI.getOperand(0).getReg();
11862 if (!MRI.hasOneNonDBGUse(DefReg))
11863 return false;
11864
11865 // It's likely that a sext/zext as a G_PTR_ADD offset will be folded into an
11866 // addressing mode.
11867 auto *UserMI = &*MRI.use_instr_nodbg_begin(DefReg);
11868 return UserMI->getOpcode() == TargetOpcode::G_PTR_ADD;
11869}
11870
11871uint64_t AArch64InstrInfo::getElementSizeForOpcode(unsigned Opc) const {
11872 return get(Opc).TSFlags & AArch64::ElementSizeMask;
11873}
11874
11875bool AArch64InstrInfo::isPTestLikeOpcode(unsigned Opc) const {
11876 return get(Opc).TSFlags & AArch64::InstrFlagIsPTestLike;
11877}
11878
11879bool AArch64InstrInfo::isWhileOpcode(unsigned Opc) const {
11880 return get(Opc).TSFlags & AArch64::InstrFlagIsWhile;
11881}
11882
11883unsigned int
11884AArch64InstrInfo::getTailDuplicateSize(CodeGenOptLevel OptLevel) const {
11885 return OptLevel >= CodeGenOptLevel::Aggressive ? 6 : 2;
11886}
11887
11888bool AArch64InstrInfo::isLegalAddressingMode(unsigned NumBytes, int64_t Offset,
11889 unsigned Scale) const {
11890 if (Offset && Scale)
11891 return false;
11892
11893 // Check Reg + Imm
11894 if (!Scale) {
11895 // 9-bit signed offset
11896 if (isInt<9>(Offset))
11897 return true;
11898
11899 // 12-bit unsigned offset
11900 unsigned Shift = Log2_64(NumBytes);
11901 if (NumBytes && Offset > 0 && (Offset / NumBytes) <= (1LL << 12) - 1 &&
11902 // Must be a multiple of NumBytes (NumBytes is a power of 2)
11903 (Offset >> Shift) << Shift == Offset)
11904 return true;
11905 return false;
11906 }
11907
11908 // Check reg1 + SIZE_IN_BYTES * reg2 and reg1 + reg2
11909 return Scale == 1 || (Scale > 0 && Scale == NumBytes);
11910}
11911
11913 if (MF.getSubtarget<AArch64Subtarget>().hardenSlsBlr())
11914 return AArch64::BLRNoIP;
11915 else
11916 return AArch64::BLR;
11917}
11918
11920 DebugLoc DL) const {
11921 MachineBasicBlock::iterator InsertPt = MBB.getFirstTerminator();
11922 auto Builder = BuildMI(MBB, InsertPt, DL, get(AArch64::PAUTH_EPILOGUE))
11924
11925 MachineFunction &MF = *MBB.getParent();
11926 const auto *AFI = MF.getInfo<AArch64FunctionInfo>();
11927 auto &AFL = *static_cast<const AArch64FrameLowering *>(
11928 MF.getSubtarget().getFrameLowering());
11929 if (AFL.getArgumentStackToRestore(MF, MBB)) {
11930 Builder.addReg(AArch64::X17, RegState::ImplicitDefine);
11931 Builder.addReg(AArch64::X16, RegState::ImplicitDefine);
11932 if (AFI->branchProtectionPAuthLR())
11933 Builder.addReg(AArch64::X15, RegState::ImplicitDefine);
11934 return;
11935 }
11936
11937 if (AFI->branchProtectionPAuthLR() && !Subtarget.hasPAuthLR())
11938 Builder.addReg(AArch64::X16, RegState::ImplicitDefine);
11939}
11940
11942AArch64InstrInfo::probedStackAlloc(MachineBasicBlock::iterator MBBI,
11943 Register TargetReg, bool FrameSetup) const {
11944 assert(TargetReg != AArch64::SP && "New top of stack cannot already be in SP");
11945
11946 MachineBasicBlock &MBB = *MBBI->getParent();
11947 MachineFunction &MF = *MBB.getParent();
11948 const AArch64InstrInfo *TII =
11949 MF.getSubtarget<AArch64Subtarget>().getInstrInfo();
11950 int64_t ProbeSize = MF.getInfo<AArch64FunctionInfo>()->getStackProbeSize();
11951 DebugLoc DL = MBB.findDebugLoc(MBBI);
11952
11953 MachineFunction::iterator MBBInsertPoint = std::next(MBB.getIterator());
11954 MachineBasicBlock *LoopTestMBB =
11955 MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11956 MF.insert(MBBInsertPoint, LoopTestMBB);
11957 MachineBasicBlock *LoopBodyMBB =
11958 MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11959 MF.insert(MBBInsertPoint, LoopBodyMBB);
11960 MachineBasicBlock *ExitMBB = MF.CreateMachineBasicBlock(MBB.getBasicBlock());
11961 MF.insert(MBBInsertPoint, ExitMBB);
11962 MachineInstr::MIFlag Flags =
11964
11965 // LoopTest:
11966 // SUB SP, SP, #ProbeSize
11967 emitFrameOffset(*LoopTestMBB, LoopTestMBB->end(), DL, AArch64::SP,
11968 AArch64::SP, StackOffset::getFixed(-ProbeSize), TII, Flags);
11969
11970 // CMP SP, TargetReg
11971 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(AArch64::SUBSXrx64),
11972 AArch64::XZR)
11973 .addReg(AArch64::SP)
11974 .addReg(TargetReg)
11976 .setMIFlags(Flags);
11977
11978 // B.<Cond> LoopExit
11979 BuildMI(*LoopTestMBB, LoopTestMBB->end(), DL, TII->get(AArch64::Bcc))
11981 .addMBB(ExitMBB)
11982 .setMIFlags(Flags);
11983
11984 // LDR XZR, [SP]
11985 BuildMI(*LoopBodyMBB, LoopBodyMBB->end(), DL, TII->get(AArch64::LDRXui))
11986 .addDef(AArch64::XZR)
11987 .addReg(AArch64::SP)
11988 .addImm(0)
11992 Align(8)))
11993 .setMIFlags(Flags);
11994
11995 // B loop
11996 BuildMI(*LoopBodyMBB, LoopBodyMBB->end(), DL, TII->get(AArch64::B))
11997 .addMBB(LoopTestMBB)
11998 .setMIFlags(Flags);
11999
12000 // LoopExit:
12001 // MOV SP, TargetReg
12002 BuildMI(*ExitMBB, ExitMBB->end(), DL, TII->get(AArch64::ADDXri), AArch64::SP)
12003 .addReg(TargetReg)
12004 .addImm(0)
12006 .setMIFlags(Flags);
12007
12008 // LDR XZR, [SP]
12009 BuildMI(*ExitMBB, ExitMBB->end(), DL, TII->get(AArch64::LDRXui))
12010 .addReg(AArch64::XZR, RegState::Define)
12011 .addReg(AArch64::SP)
12012 .addImm(0)
12013 .setMIFlags(Flags);
12014
12015 ExitMBB->splice(ExitMBB->end(), &MBB, std::next(MBBI), MBB.end());
12017
12018 LoopTestMBB->addSuccessor(ExitMBB);
12019 LoopTestMBB->addSuccessor(LoopBodyMBB);
12020 LoopBodyMBB->addSuccessor(LoopTestMBB);
12021 MBB.addSuccessor(LoopTestMBB);
12022
12023 // Update liveins.
12024 if (MF.getRegInfo().reservedRegsFrozen())
12025 fullyRecomputeLiveIns({ExitMBB, LoopBodyMBB, LoopTestMBB});
12026
12027 return ExitMBB->begin();
12028}
12029
12030namespace {
12031class AArch64PipelinerLoopInfo : public TargetInstrInfo::PipelinerLoopInfo {
12032 MachineFunction *MF;
12033 const TargetInstrInfo *TII;
12034 const TargetRegisterInfo *TRI;
12035 MachineRegisterInfo &MRI;
12036
12037 /// The block of the loop
12038 MachineBasicBlock *LoopBB;
12039 /// The conditional branch of the loop
12040 MachineInstr *CondBranch;
12041 /// The compare instruction for loop control
12042 MachineInstr *Comp;
12043 /// The number of the operand of the loop counter value in Comp
12044 unsigned CompCounterOprNum;
12045 /// The instruction that updates the loop counter value
12046 MachineInstr *Update;
12047 /// The number of the operand of the loop counter value in Update
12048 unsigned UpdateCounterOprNum;
12049 /// The initial value of the loop counter
12050 Register Init;
12051 /// True iff Update is a predecessor of Comp
12052 bool IsUpdatePriorComp;
12053
12054 /// The normalized condition used by createTripCountGreaterCondition()
12055 SmallVector<MachineOperand, 4> Cond;
12056
12057public:
12058 AArch64PipelinerLoopInfo(MachineBasicBlock *LoopBB, MachineInstr *CondBranch,
12059 MachineInstr *Comp, unsigned CompCounterOprNum,
12060 MachineInstr *Update, unsigned UpdateCounterOprNum,
12061 Register Init, bool IsUpdatePriorComp,
12062 const SmallVectorImpl<MachineOperand> &Cond)
12063 : MF(Comp->getParent()->getParent()),
12064 TII(MF->getSubtarget().getInstrInfo()),
12065 TRI(MF->getSubtarget().getRegisterInfo()), MRI(MF->getRegInfo()),
12066 LoopBB(LoopBB), CondBranch(CondBranch), Comp(Comp),
12067 CompCounterOprNum(CompCounterOprNum), Update(Update),
12068 UpdateCounterOprNum(UpdateCounterOprNum), Init(Init),
12069 IsUpdatePriorComp(IsUpdatePriorComp), Cond(Cond.begin(), Cond.end()) {}
12070
12071 bool shouldIgnoreForPipelining(const MachineInstr *MI) const override {
12072 // Make the instructions for loop control be placed in stage 0.
12073 // The predecessors of Comp are considered by the caller.
12074 return MI == Comp;
12075 }
12076
12077 std::optional<bool> createTripCountGreaterCondition(
12078 int TC, MachineBasicBlock &MBB,
12079 SmallVectorImpl<MachineOperand> &CondParam) override {
12080 // A branch instruction will be inserted as "if (Cond) goto epilogue".
12081 // Cond is normalized for such use.
12082 // The predecessors of the branch are assumed to have already been inserted.
12083 CondParam = Cond;
12084 return {};
12085 }
12086
12087 void createRemainingIterationsGreaterCondition(
12088 int TC, MachineBasicBlock &MBB, SmallVectorImpl<MachineOperand> &Cond,
12089 DenseMap<MachineInstr *, MachineInstr *> &LastStage0Insts) override;
12090
12091 void setPreheader(MachineBasicBlock *NewPreheader) override {}
12092
12093 void adjustTripCount(int TripCountAdjust) override {}
12094
12095 bool isMVEExpanderSupported() override { return true; }
12096};
12097} // namespace
12098
12099/// Clone an instruction from MI. The register of ReplaceOprNum-th operand
12100/// is replaced by ReplaceReg. The output register is newly created.
12101/// The other operands are unchanged from MI.
12102static Register cloneInstr(const MachineInstr *MI, unsigned ReplaceOprNum,
12103 Register ReplaceReg, MachineBasicBlock &MBB,
12104 MachineBasicBlock::iterator InsertTo) {
12105 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
12106 const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo();
12107 MachineInstr *NewMI = MBB.getParent()->CloneMachineInstr(MI);
12108 Register Result = 0;
12109 for (unsigned I = 0; I < NewMI->getNumOperands(); ++I) {
12110 if (I == 0 && NewMI->getOperand(0).getReg().isVirtual()) {
12111 Result = MRI.createVirtualRegister(
12112 MRI.getRegClass(NewMI->getOperand(0).getReg()));
12113 NewMI->getOperand(I).setReg(Result);
12114 } else if (I == ReplaceOprNum) {
12115 MRI.constrainRegClass(ReplaceReg, TII->getRegClass(NewMI->getDesc(), I));
12116 NewMI->getOperand(I).setReg(ReplaceReg);
12117 }
12118 }
12119 MBB.insert(InsertTo, NewMI);
12120 return Result;
12121}
12122
12123void AArch64PipelinerLoopInfo::createRemainingIterationsGreaterCondition(
12126 // Create and accumulate conditions for next TC iterations.
12127 // Example:
12128 // SUBSXrr N, counter, implicit-def $nzcv # compare instruction for the last
12129 // # iteration of the kernel
12130 //
12131 // # insert the following instructions
12132 // cond = CSINCXr 0, 0, C, implicit $nzcv
12133 // counter = ADDXri counter, 1 # clone from this->Update
12134 // SUBSXrr n, counter, implicit-def $nzcv # clone from this->Comp
12135 // cond = CSINCXr cond, cond, C, implicit $nzcv
12136 // ... (repeat TC times)
12137 // SUBSXri cond, 0, implicit-def $nzcv
12138
12139 assert(CondBranch->getOpcode() == AArch64::Bcc);
12140 // CondCode to exit the loop
12142 (AArch64CC::CondCode)CondBranch->getOperand(0).getImm();
12143 if (CondBranch->getOperand(1).getMBB() == LoopBB)
12145
12146 // Accumulate conditions to exit the loop
12147 Register AccCond = AArch64::XZR;
12148
12149 // If CC holds, CurCond+1 is returned; otherwise CurCond is returned.
12150 auto AccumulateCond = [&](Register CurCond,
12152 Register NewCond = MRI.createVirtualRegister(&AArch64::GPR64commonRegClass);
12153 BuildMI(MBB, MBB.end(), Comp->getDebugLoc(), TII->get(AArch64::CSINCXr))
12154 .addReg(NewCond, RegState::Define)
12155 .addReg(CurCond)
12156 .addReg(CurCond)
12158 return NewCond;
12159 };
12160
12161 if (!LastStage0Insts.empty() && LastStage0Insts[Comp]->getParent() == &MBB) {
12162 // Update and Comp for I==0 are already exists in MBB
12163 // (MBB is an unrolled kernel)
12164 Register Counter;
12165 for (int I = 0; I <= TC; ++I) {
12166 Register NextCounter;
12167 if (I != 0)
12168 NextCounter =
12169 cloneInstr(Comp, CompCounterOprNum, Counter, MBB, MBB.end());
12170
12171 AccCond = AccumulateCond(AccCond, CC);
12172
12173 if (I != TC) {
12174 if (I == 0) {
12175 if (Update != Comp && IsUpdatePriorComp) {
12176 Counter =
12177 LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
12178 NextCounter = cloneInstr(Update, UpdateCounterOprNum, Counter, MBB,
12179 MBB.end());
12180 } else {
12181 // can use already calculated value
12182 NextCounter = LastStage0Insts[Update]->getOperand(0).getReg();
12183 }
12184 } else if (Update != Comp) {
12185 NextCounter =
12186 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
12187 }
12188 }
12189 Counter = NextCounter;
12190 }
12191 } else {
12192 Register Counter;
12193 if (LastStage0Insts.empty()) {
12194 // use initial counter value (testing if the trip count is sufficient to
12195 // be executed by pipelined code)
12196 Counter = Init;
12197 if (IsUpdatePriorComp)
12198 Counter =
12199 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
12200 } else {
12201 // MBB is an epilogue block. LastStage0Insts[Comp] is in the kernel block.
12202 Counter = LastStage0Insts[Comp]->getOperand(CompCounterOprNum).getReg();
12203 }
12204
12205 for (int I = 0; I <= TC; ++I) {
12206 Register NextCounter;
12207 NextCounter =
12208 cloneInstr(Comp, CompCounterOprNum, Counter, MBB, MBB.end());
12209 AccCond = AccumulateCond(AccCond, CC);
12210 if (I != TC && Update != Comp)
12211 NextCounter =
12212 cloneInstr(Update, UpdateCounterOprNum, Counter, MBB, MBB.end());
12213 Counter = NextCounter;
12214 }
12215 }
12216
12217 // If AccCond == 0, the remainder is greater than TC.
12218 BuildMI(MBB, MBB.end(), Comp->getDebugLoc(), TII->get(AArch64::SUBSXri))
12219 .addReg(AArch64::XZR, RegState::Define | RegState::Dead)
12220 .addReg(AccCond)
12221 .addImm(0)
12222 .addImm(0);
12223 Cond.clear();
12225}
12226
12227static void extractPhiReg(const MachineInstr &Phi, const MachineBasicBlock *MBB,
12228 Register &RegMBB, Register &RegOther) {
12229 assert(Phi.getNumOperands() == 5);
12230 if (Phi.getOperand(2).getMBB() == MBB) {
12231 RegMBB = Phi.getOperand(1).getReg();
12232 RegOther = Phi.getOperand(3).getReg();
12233 } else {
12234 assert(Phi.getOperand(4).getMBB() == MBB);
12235 RegMBB = Phi.getOperand(3).getReg();
12236 RegOther = Phi.getOperand(1).getReg();
12237 }
12238}
12239
12241 if (!Reg.isVirtual())
12242 return false;
12243 const MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();
12244 return MRI.getDefBlock(Reg) != BB;
12245}
12246
12247/// If Reg is an induction variable, return true and set some parameters
12248static bool getIndVarInfo(Register Reg, const MachineBasicBlock *LoopBB,
12249 MachineInstr *&UpdateInst,
12250 unsigned &UpdateCounterOprNum, Register &InitReg,
12251 bool &IsUpdatePriorComp) {
12252 // Example:
12253 //
12254 // Preheader:
12255 // InitReg = ...
12256 // LoopBB:
12257 // Reg0 = PHI (InitReg, Preheader), (Reg1, LoopBB)
12258 // Reg = COPY Reg0 ; COPY is ignored.
12259 // Reg1 = ADD Reg, #1; UpdateInst. Incremented by a loop invariant value.
12260 // ; Reg is the value calculated in the previous
12261 // ; iteration, so IsUpdatePriorComp == false.
12262
12263 if (LoopBB->pred_size() != 2)
12264 return false;
12265 if (!Reg.isVirtual())
12266 return false;
12267 const MachineRegisterInfo &MRI = LoopBB->getParent()->getRegInfo();
12268 UpdateInst = nullptr;
12269 UpdateCounterOprNum = 0;
12270 InitReg = 0;
12271 IsUpdatePriorComp = true;
12272 Register CurReg = Reg;
12273 while (true) {
12274 MachineInstr *Def = MRI.getVRegDef(CurReg);
12275 if (Def->getParent() != LoopBB)
12276 return false;
12277 if (Def->isCopy()) {
12278 // Ignore copy instructions unless they contain subregisters
12279 if (Def->getOperand(0).getSubReg() || Def->getOperand(1).getSubReg())
12280 return false;
12281 CurReg = Def->getOperand(1).getReg();
12282 } else if (Def->isPHI()) {
12283 if (InitReg != 0)
12284 return false;
12285 if (!UpdateInst)
12286 IsUpdatePriorComp = false;
12287 extractPhiReg(*Def, LoopBB, CurReg, InitReg);
12288 } else {
12289 if (UpdateInst)
12290 return false;
12291 switch (Def->getOpcode()) {
12292 case AArch64::ADDSXri:
12293 case AArch64::ADDSWri:
12294 case AArch64::SUBSXri:
12295 case AArch64::SUBSWri:
12296 case AArch64::ADDXri:
12297 case AArch64::ADDWri:
12298 case AArch64::SUBXri:
12299 case AArch64::SUBWri:
12300 UpdateInst = Def;
12301 UpdateCounterOprNum = 1;
12302 break;
12303 case AArch64::ADDSXrr:
12304 case AArch64::ADDSWrr:
12305 case AArch64::SUBSXrr:
12306 case AArch64::SUBSWrr:
12307 case AArch64::ADDXrr:
12308 case AArch64::ADDWrr:
12309 case AArch64::SUBXrr:
12310 case AArch64::SUBWrr:
12311 UpdateInst = Def;
12312 if (isDefinedOutside(Def->getOperand(2).getReg(), LoopBB))
12313 UpdateCounterOprNum = 1;
12314 else if (isDefinedOutside(Def->getOperand(1).getReg(), LoopBB))
12315 UpdateCounterOprNum = 2;
12316 else
12317 return false;
12318 break;
12319 default:
12320 return false;
12321 }
12322 CurReg = Def->getOperand(UpdateCounterOprNum).getReg();
12323 }
12324
12325 if (!CurReg.isVirtual())
12326 return false;
12327 if (Reg == CurReg)
12328 break;
12329 }
12330
12331 if (!UpdateInst)
12332 return false;
12333
12334 return true;
12335}
12336
12337std::unique_ptr<TargetInstrInfo::PipelinerLoopInfo>
12339 // Accept loops that meet the following conditions
12340 // * The conditional branch is BCC
12341 // * The compare instruction is ADDS/SUBS/WHILEXX
12342 // * One operand of the compare is an induction variable and the other is a
12343 // loop invariant value
12344 // * The induction variable is incremented/decremented by a single instruction
12345 // * Does not contain CALL or instructions which have unmodeled side effects
12346
12347 for (MachineInstr &MI : *LoopBB)
12348 if (MI.isCall() || MI.hasUnmodeledSideEffects())
12349 // This instruction may use NZCV, which interferes with the instruction to
12350 // be inserted for loop control.
12351 return nullptr;
12352
12353 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
12355 if (analyzeBranch(*LoopBB, TBB, FBB, Cond))
12356 return nullptr;
12357
12358 // Infinite loops are not supported
12359 if (TBB == LoopBB && FBB == LoopBB)
12360 return nullptr;
12361
12362 // Must be conditional branch
12363 if (TBB != LoopBB && FBB == nullptr)
12364 return nullptr;
12365
12366 assert((TBB == LoopBB || FBB == LoopBB) &&
12367 "The Loop must be a single-basic-block loop");
12368
12369 MachineInstr *CondBranch = &*LoopBB->getFirstTerminator();
12371
12372 if (CondBranch->getOpcode() != AArch64::Bcc)
12373 return nullptr;
12374
12375 // Normalization for createTripCountGreaterCondition()
12376 if (TBB == LoopBB)
12378
12379 MachineInstr *Comp = nullptr;
12380 unsigned CompCounterOprNum = 0;
12381 for (MachineInstr &MI : reverse(*LoopBB)) {
12382 if (MI.modifiesRegister(AArch64::NZCV, &TRI)) {
12383 // Guarantee that the compare is SUBS/ADDS/WHILEXX and that one of the
12384 // operands is a loop invariant value
12385
12386 switch (MI.getOpcode()) {
12387 case AArch64::SUBSXri:
12388 case AArch64::SUBSWri:
12389 case AArch64::ADDSXri:
12390 case AArch64::ADDSWri:
12391 Comp = &MI;
12392 CompCounterOprNum = 1;
12393 break;
12394 case AArch64::ADDSWrr:
12395 case AArch64::ADDSXrr:
12396 case AArch64::SUBSWrr:
12397 case AArch64::SUBSXrr:
12398 Comp = &MI;
12399 break;
12400 default:
12401 if (isWhileOpcode(MI.getOpcode())) {
12402 Comp = &MI;
12403 break;
12404 }
12405 return nullptr;
12406 }
12407
12408 if (CompCounterOprNum == 0) {
12409 if (isDefinedOutside(Comp->getOperand(1).getReg(), LoopBB))
12410 CompCounterOprNum = 2;
12411 else if (isDefinedOutside(Comp->getOperand(2).getReg(), LoopBB))
12412 CompCounterOprNum = 1;
12413 else
12414 return nullptr;
12415 }
12416 break;
12417 }
12418 }
12419 if (!Comp)
12420 return nullptr;
12421
12422 MachineInstr *Update = nullptr;
12423 Register Init;
12424 bool IsUpdatePriorComp;
12425 unsigned UpdateCounterOprNum;
12426 if (!getIndVarInfo(Comp->getOperand(CompCounterOprNum).getReg(), LoopBB,
12427 Update, UpdateCounterOprNum, Init, IsUpdatePriorComp))
12428 return nullptr;
12429
12430 return std::make_unique<AArch64PipelinerLoopInfo>(
12431 LoopBB, CondBranch, Comp, CompCounterOprNum, Update, UpdateCounterOprNum,
12432 Init, IsUpdatePriorComp, Cond);
12433}
12434
12435/// verifyInstruction - Perform target specific instruction verification.
12436bool AArch64InstrInfo::verifyInstruction(const MachineInstr &MI,
12437 StringRef &ErrInfo) const {
12438 // Verify that immediate offsets on load/store instructions are within range.
12439 // Stack objects with an FI operand are excluded as they can be fixed up
12440 // during PEI.
12441 TypeSize Scale(0U, false), Width(0U, false);
12442 int64_t MinOffset, MaxOffset;
12443 if (getMemOpInfo(MI.getOpcode(), Scale, Width, MinOffset, MaxOffset)) {
12444 unsigned ImmIdx = getLoadStoreImmIdx(MI.getOpcode());
12445 if (MI.getOperand(ImmIdx).isImm() && !MI.getOperand(ImmIdx - 1).isFI()) {
12446 int64_t Imm = MI.getOperand(ImmIdx).getImm();
12447 if (Imm < MinOffset || Imm > MaxOffset) {
12448 ErrInfo = "Unexpected immediate on load/store instruction";
12449 return false;
12450 }
12451 }
12452 }
12453
12454 const MCInstrDesc &MCID = MI.getDesc();
12455 for (unsigned Op = 0; Op < MCID.getNumOperands(); Op++) {
12456 const MachineOperand &MO = MI.getOperand(Op);
12457 switch (MCID.operands()[Op].OperandType) {
12459 if (!MO.isImm() || MO.getImm() != 0) {
12460 ErrInfo = "OPERAND_IMPLICIT_IMM_0 should be 0";
12461 return false;
12462 }
12463 break;
12465 if (!MO.isImm() ||
12467 (AArch64_AM::getShiftValue(MO.getImm()) != 8 &&
12468 AArch64_AM::getShiftValue(MO.getImm()) != 16)) {
12469 ErrInfo = "OPERAND_SHIFT_MSL should be msl shift of 8 or 16";
12470 return false;
12471 }
12472 break;
12474 if (!MO.isImm() || (MO.getImm() != 0 && MO.getImm() != 1)) {
12475 ErrInfo = "OPERAND_IMM_UINT1 should be 0 or 1";
12476 return false;
12477 }
12478 break;
12480 if (!MO.isImm() || MO.getImm() <= 0 || MO.getImm() > 16) {
12481 ErrInfo = "OPERAND_IMM_UINT4plus1 should be in the range 1 to 16";
12482 return false;
12483 }
12484 break;
12486 if (!MO.isImm() || !isUInt<5>(MO.getImm())) {
12487 ErrInfo = "OPERAND_IMM_UINT5 should be in the range 0 to 31";
12488 return false;
12489 }
12490 break;
12492 if (!MO.isImm() || !isUInt<8>(MO.getImm())) {
12493 ErrInfo = "OPERAND_IMM_UINT8 should be in the range 0 to 255";
12494 return false;
12495 }
12496 break;
12497 default:
12498 break;
12499 }
12500 }
12501 return true;
12502}
12503
12504#define GET_INSTRINFO_HELPERS
12505#define GET_INSTRMAP_INFO
12506#include "AArch64GenInstrInfo.inc"
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
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 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 unsigned getBranchDisplacementBits(const AArch64Options &CLOpts, unsigned Opc)
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 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 genMaddShf(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, SmallVectorImpl< MachineInstr * > &DelInstrs, unsigned MaddOpc, bool Is64Bit, DenseMap< Register, unsigned > &InstrIdxForVirtReg)
MUL I=A,B,0 ADDrs R,I,C,shift ==> SBFM/UBFM J=C,shift MADD R,A,B,J.
static void appendReadRegExpr(SmallVectorImpl< char > &Expr, unsigned RegNum)
static MachineInstr * genMaddR(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, unsigned VR, const TargetRegisterClass *RC)
genMaddR - Generate madd instruction and combine mul and add using an extra virtual register Example ...
static Register cloneInstr(const MachineInstr *MI, unsigned ReplaceOprNum, Register ReplaceReg, MachineBasicBlock &MBB, MachineBasicBlock::iterator InsertTo)
Clone an instruction from MI.
static bool scaleOffset(unsigned Opc, int64_t &Offset)
static bool canCombineWithFMUL(MachineBasicBlock &MBB, MachineOperand &MO, unsigned MulOpc)
unsigned scaledOffsetOpcode(unsigned Opcode, unsigned &Scale)
static MachineInstr * genFusedMultiplyIdx(MachineFunction &MF, MachineRegisterInfo &MRI, const TargetInstrInfo *TII, MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxMulOpd, unsigned MaddOpc, const TargetRegisterClass *RC)
genFusedMultiplyIdx - Helper to generate fused multiply accumulate instructions.
static MachineInstr * genIndexedMultiply(MachineInstr &Root, SmallVectorImpl< MachineInstr * > &InsInstrs, unsigned IdxDupOp, unsigned MulOpc, const TargetRegisterClass *RC, MachineRegisterInfo &MRI)
Fold (FMUL x (DUP y lane)) into (FMUL_indexed x y lane)
static bool 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 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 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 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)
unsigned RegSize
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
uint64_t Imm
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
SmallVector< MachineOperand, 4 > Cond
RISCVCC::CondCode CC
MachineRegisterInfo & MRI
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
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:480
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
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.
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
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
bool getMemOperandsWithOffsetWidth(const MachineInstr &MI, SmallVectorImpl< const MachineOperand * > &BaseOps, int64_t &Offset, bool &OffsetIsScalable, LocationSize &Width) 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.
bool canInsertSelect(const MachineBasicBlock &, ArrayRef< MachineOperand > Cond, Register, Register, Register, SelectExpansion &) const override
MachineOperand & getMemOpBaseRegImmOfsOffsetOperand(MachineInstr &LdSt) const
Return the immediate offset of the base register in a load/store LdSt.
std::optional< ExtAddrMode > getAddrModeFromMemoryOp(const MachineInstr &MemI) const override
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 getMemOperandWithOffsetWidth(const MachineInstr &MI, const MachineOperand *&BaseOp, int64_t &Offset, bool &OffsetIsScalable, TypeSize &Width) const
If OffsetIsScalable is set to 'true', the offset is scaled by vscale.
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:44
A debug info location.
Definition DebugLoc.h:126
bool empty() const
Definition DenseMap.h:716
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:827
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
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.
bool usesWindowsUnwindInfo() const
True if this function describes its unwind information with Windows SEH unwind opcodes (....
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.
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
const Triple & getTargetTriple() const
Get the target triple which is a string describing the target host.
Definition Module.h:328
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:31
int64_t getFixed() const
Returns the fixed component of the stack.
Definition TypeSize.h:47
int64_t getScalable() const
Returns the scalable component of the stack.
Definition TypeSize.h:50
static StackOffset get(int64_t Fixed, int64_t Scalable)
Definition TypeSize.h:42
static StackOffset getScalable(int64_t Scalable)
Definition TypeSize.h:41
static StackOffset getFixed(int64_t Fixed)
Definition TypeSize.h:40
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 isFunctionSafeToOutlineFrom(MachineFunction &MF, bool OutlineFromLinkOnceODRs) const
Return true if the function can safely be outlined from.
virtual bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const
Test if the given instruction should be considered a scheduling boundary.
virtual CombinerObjective getCombinerObjective(unsigned Pattern) const
Return the objective of a combiner pattern.
virtual bool isFunctionSafeToSplit(const MachineFunction &MF) const
Return true if the function is a viable candidate for machine function splitting.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
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:876
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:348
static constexpr TypeSize getScalable(ScalarTy MinimumSize)
Definition TypeSize.h:351
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:169
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
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.
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.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
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
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:267
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.