LLVM 22.0.0git
AArch64ExpandPseudoInsts.cpp
Go to the documentation of this file.
1//===- AArch64ExpandPseudoInsts.cpp - Expand pseudo instructions ----------===//
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 a pass that expands pseudo instructions into target
10// instructions to allow proper scheduling and other late optimizations. This
11// pass should be run after register allocation but before the post-regalloc
12// scheduling pass.
13//
14//===----------------------------------------------------------------------===//
15
16#include "AArch64ExpandImm.h"
17#include "AArch64InstrInfo.h"
19#include "AArch64Subtarget.h"
31#include "llvm/IR/DebugLoc.h"
32#include "llvm/MC/MCInstrDesc.h"
33#include "llvm/Pass.h"
37#include <cassert>
38#include <cstdint>
39#include <iterator>
40
41using namespace llvm;
42
43#define AARCH64_EXPAND_PSEUDO_NAME "AArch64 pseudo instruction expansion pass"
44
45namespace {
46
47class AArch64ExpandPseudo : public MachineFunctionPass {
48public:
49 const AArch64InstrInfo *TII;
50
51 static char ID;
52
53 AArch64ExpandPseudo() : MachineFunctionPass(ID) {}
54
55 bool runOnMachineFunction(MachineFunction &Fn) override;
56
57 StringRef getPassName() const override { return AARCH64_EXPAND_PSEUDO_NAME; }
58
59private:
60 bool expandMBB(MachineBasicBlock &MBB);
63 bool expandMultiVecPseudo(MachineBasicBlock &MBB,
65 TargetRegisterClass ContiguousClass,
66 TargetRegisterClass StridedClass,
67 unsigned ContiguousOpc, unsigned StridedOpc);
68 bool expandFormTuplePseudo(MachineBasicBlock &MBB,
71 unsigned Size);
73 unsigned BitSize);
74
75 bool expand_DestructiveOp(MachineInstr &MI, MachineBasicBlock &MBB,
78 unsigned LdarOp, unsigned StlrOp, unsigned CmpOp,
79 unsigned ExtendImm, unsigned ZeroReg,
81 bool expandCMP_SWAP_128(MachineBasicBlock &MBB,
84 bool expandSetTagLoop(MachineBasicBlock &MBB,
87 bool expandSVESpillFill(MachineBasicBlock &MBB,
89 unsigned N);
90 bool expandCALL_RVMARKER(MachineBasicBlock &MBB,
93 bool expandStoreSwiftAsyncContext(MachineBasicBlock &MBB,
96 expandCommitOrRestoreZASave(MachineBasicBlock &MBB,
98 MachineBasicBlock *expandCondSMToggle(MachineBasicBlock &MBB,
100};
101
102} // end anonymous namespace
103
104char AArch64ExpandPseudo::ID = 0;
105
106INITIALIZE_PASS(AArch64ExpandPseudo, "aarch64-expand-pseudo",
107 AARCH64_EXPAND_PSEUDO_NAME, false, false)
108
109/// Transfer implicit operands on the pseudo instruction to the
110/// instructions created from the expansion.
111static void transferImpOps(MachineInstr &OldMI, MachineInstrBuilder &UseMI,
113 const MCInstrDesc &Desc = OldMI.getDesc();
114 for (const MachineOperand &MO :
115 llvm::drop_begin(OldMI.operands(), Desc.getNumOperands())) {
116 assert(MO.isReg() && MO.getReg());
117 if (MO.isUse())
118 UseMI.add(MO);
119 else
120 DefMI.add(MO);
121 }
122}
123
124/// Expand a MOVi32imm or MOVi64imm pseudo instruction to one or more
125/// real move-immediate instructions to synthesize the immediate.
126bool AArch64ExpandPseudo::expandMOVImm(MachineBasicBlock &MBB,
128 unsigned BitSize) {
129 MachineInstr &MI = *MBBI;
130 Register DstReg = MI.getOperand(0).getReg();
131 uint64_t RenamableState =
132 MI.getOperand(0).isRenamable() ? RegState::Renamable : 0;
133 uint64_t Imm = MI.getOperand(1).getImm();
134
135 if (DstReg == AArch64::XZR || DstReg == AArch64::WZR) {
136 // Useless def, and we don't want to risk creating an invalid ORR (which
137 // would really write to sp).
138 MI.eraseFromParent();
139 return true;
140 }
141
143 AArch64_IMM::expandMOVImm(Imm, BitSize, Insn);
144 assert(Insn.size() != 0);
145
147 for (auto I = Insn.begin(), E = Insn.end(); I != E; ++I) {
148 bool LastItem = std::next(I) == E;
149 switch (I->Opcode)
150 {
151 default: llvm_unreachable("unhandled!"); break;
152
153 case AArch64::ORRWri:
154 case AArch64::ORRXri:
155 if (I->Op1 == 0) {
156 MIBS.push_back(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
157 .add(MI.getOperand(0))
158 .addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
159 .addImm(I->Op2));
160 } else {
161 Register DstReg = MI.getOperand(0).getReg();
162 bool DstIsDead = MI.getOperand(0).isDead();
163 MIBS.push_back(
164 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
165 .addReg(DstReg, RegState::Define |
166 getDeadRegState(DstIsDead && LastItem) |
167 RenamableState)
168 .addReg(DstReg)
169 .addImm(I->Op2));
170 }
171 break;
172 case AArch64::ORRWrs:
173 case AArch64::ORRXrs: {
174 Register DstReg = MI.getOperand(0).getReg();
175 bool DstIsDead = MI.getOperand(0).isDead();
176 MIBS.push_back(
177 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
178 .addReg(DstReg, RegState::Define |
179 getDeadRegState(DstIsDead && LastItem) |
180 RenamableState)
181 .addReg(DstReg)
182 .addReg(DstReg)
183 .addImm(I->Op2));
184 } break;
185 case AArch64::ANDXri:
186 case AArch64::EORXri:
187 if (I->Op1 == 0) {
188 MIBS.push_back(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
189 .add(MI.getOperand(0))
190 .addReg(BitSize == 32 ? AArch64::WZR : AArch64::XZR)
191 .addImm(I->Op2));
192 } else {
193 Register DstReg = MI.getOperand(0).getReg();
194 bool DstIsDead = MI.getOperand(0).isDead();
195 MIBS.push_back(
196 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
197 .addReg(DstReg, RegState::Define |
198 getDeadRegState(DstIsDead && LastItem) |
199 RenamableState)
200 .addReg(DstReg)
201 .addImm(I->Op2));
202 }
203 break;
204 case AArch64::MOVNWi:
205 case AArch64::MOVNXi:
206 case AArch64::MOVZWi:
207 case AArch64::MOVZXi: {
208 bool DstIsDead = MI.getOperand(0).isDead();
209 MIBS.push_back(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
210 .addReg(DstReg, RegState::Define |
211 getDeadRegState(DstIsDead && LastItem) |
212 RenamableState)
213 .addImm(I->Op1)
214 .addImm(I->Op2));
215 } break;
216 case AArch64::MOVKWi:
217 case AArch64::MOVKXi: {
218 Register DstReg = MI.getOperand(0).getReg();
219 bool DstIsDead = MI.getOperand(0).isDead();
220 MIBS.push_back(BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(I->Opcode))
221 .addReg(DstReg,
223 getDeadRegState(DstIsDead && LastItem) |
224 RenamableState)
225 .addReg(DstReg)
226 .addImm(I->Op1)
227 .addImm(I->Op2));
228 } break;
229 }
230 }
231 transferImpOps(MI, MIBS.front(), MIBS.back());
232 MI.eraseFromParent();
233 return true;
234}
235
236bool AArch64ExpandPseudo::expandCMP_SWAP(
238 unsigned StlrOp, unsigned CmpOp, unsigned ExtendImm, unsigned ZeroReg,
239 MachineBasicBlock::iterator &NextMBBI) {
240 MachineInstr &MI = *MBBI;
241 MIMetadata MIMD(MI);
242 const MachineOperand &Dest = MI.getOperand(0);
243 Register StatusReg = MI.getOperand(1).getReg();
244 bool StatusDead = MI.getOperand(1).isDead();
245 // Duplicating undef operands into 2 instructions does not guarantee the same
246 // value on both; However undef should be replaced by xzr anyway.
247 assert(!MI.getOperand(2).isUndef() && "cannot handle undef");
248 Register AddrReg = MI.getOperand(2).getReg();
249 Register DesiredReg = MI.getOperand(3).getReg();
250 Register NewReg = MI.getOperand(4).getReg();
251
253 auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
254 auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
255 auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
256
257 MF->insert(++MBB.getIterator(), LoadCmpBB);
258 MF->insert(++LoadCmpBB->getIterator(), StoreBB);
259 MF->insert(++StoreBB->getIterator(), DoneBB);
260
261 // .Lloadcmp:
262 // mov wStatus, 0
263 // ldaxr xDest, [xAddr]
264 // cmp xDest, xDesired
265 // b.ne .Ldone
266 if (!StatusDead)
267 BuildMI(LoadCmpBB, MIMD, TII->get(AArch64::MOVZWi), StatusReg)
268 .addImm(0).addImm(0);
269 BuildMI(LoadCmpBB, MIMD, TII->get(LdarOp), Dest.getReg())
270 .addReg(AddrReg);
271 BuildMI(LoadCmpBB, MIMD, TII->get(CmpOp), ZeroReg)
272 .addReg(Dest.getReg(), getKillRegState(Dest.isDead()))
273 .addReg(DesiredReg)
274 .addImm(ExtendImm);
275 BuildMI(LoadCmpBB, MIMD, TII->get(AArch64::Bcc))
277 .addMBB(DoneBB)
278 .addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
279 LoadCmpBB->addSuccessor(DoneBB);
280 LoadCmpBB->addSuccessor(StoreBB);
281
282 // .Lstore:
283 // stlxr wStatus, xNew, [xAddr]
284 // cbnz wStatus, .Lloadcmp
285 BuildMI(StoreBB, MIMD, TII->get(StlrOp), StatusReg)
286 .addReg(NewReg)
287 .addReg(AddrReg);
288 BuildMI(StoreBB, MIMD, TII->get(AArch64::CBNZW))
289 .addReg(StatusReg, getKillRegState(StatusDead))
290 .addMBB(LoadCmpBB);
291 StoreBB->addSuccessor(LoadCmpBB);
292 StoreBB->addSuccessor(DoneBB);
293
294 DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
295 DoneBB->transferSuccessors(&MBB);
296
297 MBB.addSuccessor(LoadCmpBB);
298
299 NextMBBI = MBB.end();
300 MI.eraseFromParent();
301
302 // Recompute livein lists.
303 LivePhysRegs LiveRegs;
304 computeAndAddLiveIns(LiveRegs, *DoneBB);
305 computeAndAddLiveIns(LiveRegs, *StoreBB);
306 computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
307 // Do an extra pass around the loop to get loop carried registers right.
308 StoreBB->clearLiveIns();
309 computeAndAddLiveIns(LiveRegs, *StoreBB);
310 LoadCmpBB->clearLiveIns();
311 computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
312
313 return true;
314}
315
316bool AArch64ExpandPseudo::expandCMP_SWAP_128(
318 MachineBasicBlock::iterator &NextMBBI) {
319 MachineInstr &MI = *MBBI;
320 MIMetadata MIMD(MI);
321 MachineOperand &DestLo = MI.getOperand(0);
322 MachineOperand &DestHi = MI.getOperand(1);
323 Register StatusReg = MI.getOperand(2).getReg();
324 bool StatusDead = MI.getOperand(2).isDead();
325 // Duplicating undef operands into 2 instructions does not guarantee the same
326 // value on both; However undef should be replaced by xzr anyway.
327 assert(!MI.getOperand(3).isUndef() && "cannot handle undef");
328 Register AddrReg = MI.getOperand(3).getReg();
329 Register DesiredLoReg = MI.getOperand(4).getReg();
330 Register DesiredHiReg = MI.getOperand(5).getReg();
331 Register NewLoReg = MI.getOperand(6).getReg();
332 Register NewHiReg = MI.getOperand(7).getReg();
333
334 unsigned LdxpOp, StxpOp;
335
336 switch (MI.getOpcode()) {
337 case AArch64::CMP_SWAP_128_MONOTONIC:
338 LdxpOp = AArch64::LDXPX;
339 StxpOp = AArch64::STXPX;
340 break;
341 case AArch64::CMP_SWAP_128_RELEASE:
342 LdxpOp = AArch64::LDXPX;
343 StxpOp = AArch64::STLXPX;
344 break;
345 case AArch64::CMP_SWAP_128_ACQUIRE:
346 LdxpOp = AArch64::LDAXPX;
347 StxpOp = AArch64::STXPX;
348 break;
349 case AArch64::CMP_SWAP_128:
350 LdxpOp = AArch64::LDAXPX;
351 StxpOp = AArch64::STLXPX;
352 break;
353 default:
354 llvm_unreachable("Unexpected opcode");
355 }
356
358 auto LoadCmpBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
359 auto StoreBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
360 auto FailBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
361 auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
362
363 MF->insert(++MBB.getIterator(), LoadCmpBB);
364 MF->insert(++LoadCmpBB->getIterator(), StoreBB);
365 MF->insert(++StoreBB->getIterator(), FailBB);
366 MF->insert(++FailBB->getIterator(), DoneBB);
367
368 // .Lloadcmp:
369 // ldaxp xDestLo, xDestHi, [xAddr]
370 // cmp xDestLo, xDesiredLo
371 // sbcs xDestHi, xDesiredHi
372 // b.ne .Ldone
373 BuildMI(LoadCmpBB, MIMD, TII->get(LdxpOp))
374 .addReg(DestLo.getReg(), RegState::Define)
375 .addReg(DestHi.getReg(), RegState::Define)
376 .addReg(AddrReg);
377 BuildMI(LoadCmpBB, MIMD, TII->get(AArch64::SUBSXrs), AArch64::XZR)
378 .addReg(DestLo.getReg(), getKillRegState(DestLo.isDead()))
379 .addReg(DesiredLoReg)
380 .addImm(0);
381 BuildMI(LoadCmpBB, MIMD, TII->get(AArch64::CSINCWr), StatusReg)
382 .addUse(AArch64::WZR)
383 .addUse(AArch64::WZR)
385 BuildMI(LoadCmpBB, MIMD, TII->get(AArch64::SUBSXrs), AArch64::XZR)
386 .addReg(DestHi.getReg(), getKillRegState(DestHi.isDead()))
387 .addReg(DesiredHiReg)
388 .addImm(0);
389 BuildMI(LoadCmpBB, MIMD, TII->get(AArch64::CSINCWr), StatusReg)
390 .addUse(StatusReg, RegState::Kill)
391 .addUse(StatusReg, RegState::Kill)
393 BuildMI(LoadCmpBB, MIMD, TII->get(AArch64::CBNZW))
394 .addUse(StatusReg, getKillRegState(StatusDead))
395 .addMBB(FailBB);
396 LoadCmpBB->addSuccessor(FailBB);
397 LoadCmpBB->addSuccessor(StoreBB);
398
399 // .Lstore:
400 // stlxp wStatus, xNewLo, xNewHi, [xAddr]
401 // cbnz wStatus, .Lloadcmp
402 BuildMI(StoreBB, MIMD, TII->get(StxpOp), StatusReg)
403 .addReg(NewLoReg)
404 .addReg(NewHiReg)
405 .addReg(AddrReg);
406 BuildMI(StoreBB, MIMD, TII->get(AArch64::CBNZW))
407 .addReg(StatusReg, getKillRegState(StatusDead))
408 .addMBB(LoadCmpBB);
409 BuildMI(StoreBB, MIMD, TII->get(AArch64::B)).addMBB(DoneBB);
410 StoreBB->addSuccessor(LoadCmpBB);
411 StoreBB->addSuccessor(DoneBB);
412
413 // .Lfail:
414 // stlxp wStatus, xDestLo, xDestHi, [xAddr]
415 // cbnz wStatus, .Lloadcmp
416 BuildMI(FailBB, MIMD, TII->get(StxpOp), StatusReg)
417 .addReg(DestLo.getReg())
418 .addReg(DestHi.getReg())
419 .addReg(AddrReg);
420 BuildMI(FailBB, MIMD, TII->get(AArch64::CBNZW))
421 .addReg(StatusReg, getKillRegState(StatusDead))
422 .addMBB(LoadCmpBB);
423 FailBB->addSuccessor(LoadCmpBB);
424 FailBB->addSuccessor(DoneBB);
425
426 DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
427 DoneBB->transferSuccessors(&MBB);
428
429 MBB.addSuccessor(LoadCmpBB);
430
431 NextMBBI = MBB.end();
432 MI.eraseFromParent();
433
434 // Recompute liveness bottom up.
435 LivePhysRegs LiveRegs;
436 computeAndAddLiveIns(LiveRegs, *DoneBB);
437 computeAndAddLiveIns(LiveRegs, *FailBB);
438 computeAndAddLiveIns(LiveRegs, *StoreBB);
439 computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
440
441 // Do an extra pass in the loop to get the loop carried dependencies right.
442 FailBB->clearLiveIns();
443 computeAndAddLiveIns(LiveRegs, *FailBB);
444 StoreBB->clearLiveIns();
445 computeAndAddLiveIns(LiveRegs, *StoreBB);
446 LoadCmpBB->clearLiveIns();
447 computeAndAddLiveIns(LiveRegs, *LoadCmpBB);
448
449 return true;
450}
451
452/// \brief Expand Pseudos to Instructions with destructive operands.
453///
454/// This mechanism uses MOVPRFX instructions for zeroing the false lanes
455/// or for fixing relaxed register allocation conditions to comply with
456/// the instructions register constraints. The latter case may be cheaper
457/// than setting the register constraints in the register allocator,
458/// since that will insert regular MOV instructions rather than MOVPRFX.
459///
460/// Example (after register allocation):
461///
462/// FSUB_ZPZZ_ZERO_B Z0, Pg, Z1, Z0
463///
464/// * The Pseudo FSUB_ZPZZ_ZERO_B maps to FSUB_ZPmZ_B.
465/// * We cannot map directly to FSUB_ZPmZ_B because the register
466/// constraints of the instruction are not met.
467/// * Also the _ZERO specifies the false lanes need to be zeroed.
468///
469/// We first try to see if the destructive operand == result operand,
470/// if not, we try to swap the operands, e.g.
471///
472/// FSUB_ZPmZ_B Z0, Pg/m, Z0, Z1
473///
474/// But because FSUB_ZPmZ is not commutative, this is semantically
475/// different, so we need a reverse instruction:
476///
477/// FSUBR_ZPmZ_B Z0, Pg/m, Z0, Z1
478///
479/// Then we implement the zeroing of the false lanes of Z0 by adding
480/// a zeroing MOVPRFX instruction:
481///
482/// MOVPRFX_ZPzZ_B Z0, Pg/z, Z0
483/// FSUBR_ZPmZ_B Z0, Pg/m, Z0, Z1
484///
485/// Note that this can only be done for _ZERO or _UNDEF variants where
486/// we can guarantee the false lanes to be zeroed (by implementing this)
487/// or that they are undef (don't care / not used), otherwise the
488/// swapping of operands is illegal because the operation is not
489/// (or cannot be emulated to be) fully commutative.
490bool AArch64ExpandPseudo::expand_DestructiveOp(
494 unsigned Opcode = AArch64::getSVEPseudoMap(MI.getOpcode());
495 uint64_t DType = TII->get(Opcode).TSFlags & AArch64::DestructiveInstTypeMask;
496 uint64_t FalseLanes = MI.getDesc().TSFlags & AArch64::FalseLanesMask;
497 bool FalseZero = FalseLanes == AArch64::FalseLanesZero;
498 Register DstReg = MI.getOperand(0).getReg();
499 bool DstIsDead = MI.getOperand(0).isDead();
500 bool UseRev = false;
501 unsigned PredIdx, DOPIdx, SrcIdx, Src2Idx;
502
503 switch (DType) {
506 if (DstReg == MI.getOperand(3).getReg()) {
507 // FSUB Zd, Pg, Zs1, Zd ==> FSUBR Zd, Pg/m, Zd, Zs1
508 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 3, 2);
509 UseRev = true;
510 break;
511 }
512 [[fallthrough]];
515 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(1, 2, 3);
516 break;
518 std::tie(PredIdx, DOPIdx, SrcIdx) = std::make_tuple(2, 3, 3);
519 break;
521 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 2, 3, 4);
522 if (DstReg == MI.getOperand(3).getReg()) {
523 // FMLA Zd, Pg, Za, Zd, Zm ==> FMAD Zdn, Pg, Zm, Za
524 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 3, 4, 2);
525 UseRev = true;
526 } else if (DstReg == MI.getOperand(4).getReg()) {
527 // FMLA Zd, Pg, Za, Zm, Zd ==> FMAD Zdn, Pg, Zm, Za
528 std::tie(PredIdx, DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 4, 3, 2);
529 UseRev = true;
530 }
531 break;
533 // EXT_ZZI_CONSTRUCTIVE Zd, Zs, Imm
534 // ==> MOVPRFX Zd Zs; EXT_ZZI Zd, Zd, Zs, Imm
535 std::tie(DOPIdx, SrcIdx, Src2Idx) = std::make_tuple(1, 1, 2);
536 break;
537 default:
538 llvm_unreachable("Unsupported Destructive Operand type");
539 }
540
541 // MOVPRFX can only be used if the destination operand
542 // is the destructive operand, not as any other operand,
543 // so the Destructive Operand must be unique.
544 bool DOPRegIsUnique = false;
545 switch (DType) {
547 DOPRegIsUnique = DstReg != MI.getOperand(SrcIdx).getReg();
548 break;
551 DOPRegIsUnique =
552 DstReg != MI.getOperand(DOPIdx).getReg() ||
553 MI.getOperand(DOPIdx).getReg() != MI.getOperand(SrcIdx).getReg();
554 break;
558 DOPRegIsUnique = true;
559 break;
561 DOPRegIsUnique =
562 DstReg != MI.getOperand(DOPIdx).getReg() ||
563 (MI.getOperand(DOPIdx).getReg() != MI.getOperand(SrcIdx).getReg() &&
564 MI.getOperand(DOPIdx).getReg() != MI.getOperand(Src2Idx).getReg());
565 break;
566 }
567
568 // Resolve the reverse opcode
569 if (UseRev) {
570 int NewOpcode;
571 // e.g. DIV -> DIVR
572 if ((NewOpcode = AArch64::getSVERevInstr(Opcode)) != -1)
573 Opcode = NewOpcode;
574 // e.g. DIVR -> DIV
575 else if ((NewOpcode = AArch64::getSVENonRevInstr(Opcode)) != -1)
576 Opcode = NewOpcode;
577 }
578
579 // Get the right MOVPRFX
580 uint64_t ElementSize = TII->getElementSizeForOpcode(Opcode);
581 unsigned MovPrfx, LSLZero, MovPrfxZero;
582 switch (ElementSize) {
585 MovPrfx = AArch64::MOVPRFX_ZZ;
586 LSLZero = AArch64::LSL_ZPmI_B;
587 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_B;
588 break;
590 MovPrfx = AArch64::MOVPRFX_ZZ;
591 LSLZero = AArch64::LSL_ZPmI_H;
592 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_H;
593 break;
595 MovPrfx = AArch64::MOVPRFX_ZZ;
596 LSLZero = AArch64::LSL_ZPmI_S;
597 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_S;
598 break;
600 MovPrfx = AArch64::MOVPRFX_ZZ;
601 LSLZero = AArch64::LSL_ZPmI_D;
602 MovPrfxZero = AArch64::MOVPRFX_ZPzZ_D;
603 break;
604 default:
605 llvm_unreachable("Unsupported ElementSize");
606 }
607
608 // Preserve undef state until DOP's reg is defined.
609 unsigned DOPRegState = MI.getOperand(DOPIdx).isUndef() ? RegState::Undef : 0;
610
611 //
612 // Create the destructive operation (if required)
613 //
614 MachineInstrBuilder PRFX, DOP;
615 if (FalseZero) {
616 // If we cannot prefix the requested instruction we'll instead emit a
617 // prefixed_zeroing_mov for DestructiveBinary.
618 assert((DOPRegIsUnique || DType == AArch64::DestructiveBinary ||
621 "The destructive operand should be unique");
622 assert(ElementSize != AArch64::ElementSizeNone &&
623 "This instruction is unpredicated");
624
625 // Merge source operand into destination register
626 PRFX = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(MovPrfxZero))
627 .addReg(DstReg, RegState::Define)
628 .addReg(MI.getOperand(PredIdx).getReg())
629 .addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState);
630
631 // After the movprfx, the destructive operand is same as Dst
632 DOPIdx = 0;
633 DOPRegState = 0;
634
635 // Create the additional LSL to zero the lanes when the DstReg is not
636 // unique. Zeros the lanes in z0 that aren't active in p0 with sequence
637 // movprfx z0.b, p0/z, z0.b; lsl z0.b, p0/m, z0.b, #0;
638 if ((DType == AArch64::DestructiveBinary ||
641 !DOPRegIsUnique) {
642 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(LSLZero))
643 .addReg(DstReg, RegState::Define)
644 .add(MI.getOperand(PredIdx))
645 .addReg(DstReg)
646 .addImm(0);
647 }
648 } else if (DstReg != MI.getOperand(DOPIdx).getReg()) {
649 assert(DOPRegIsUnique && "The destructive operand should be unique");
650 PRFX = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(MovPrfx))
651 .addReg(DstReg, RegState::Define)
652 .addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState);
653 DOPIdx = 0;
654 DOPRegState = 0;
655 }
656
657 //
658 // Create the destructive operation
659 //
660 DOP = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opcode))
661 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead));
662 DOPRegState = DOPRegState | RegState::Kill;
663
664 switch (DType) {
666 DOP.addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState)
667 .add(MI.getOperand(PredIdx))
668 .add(MI.getOperand(SrcIdx));
669 break;
674 DOP.add(MI.getOperand(PredIdx))
675 .addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState)
676 .add(MI.getOperand(SrcIdx));
677 break;
679 DOP.add(MI.getOperand(PredIdx))
680 .addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState)
681 .add(MI.getOperand(SrcIdx))
682 .add(MI.getOperand(Src2Idx));
683 break;
685 DOP.addReg(MI.getOperand(DOPIdx).getReg(), DOPRegState)
686 .add(MI.getOperand(SrcIdx))
687 .add(MI.getOperand(Src2Idx));
688 break;
689 }
690
691 if (PRFX) {
692 transferImpOps(MI, PRFX, DOP);
694 } else
695 transferImpOps(MI, DOP, DOP);
696
697 MI.eraseFromParent();
698 return true;
699}
700
701bool AArch64ExpandPseudo::expandSetTagLoop(
703 MachineBasicBlock::iterator &NextMBBI) {
704 MachineInstr &MI = *MBBI;
705 DebugLoc DL = MI.getDebugLoc();
706 Register SizeReg = MI.getOperand(0).getReg();
707 Register AddressReg = MI.getOperand(1).getReg();
708
710
711 bool ZeroData = MI.getOpcode() == AArch64::STZGloop_wback;
712 const unsigned OpCode1 =
713 ZeroData ? AArch64::STZGPostIndex : AArch64::STGPostIndex;
714 const unsigned OpCode2 =
715 ZeroData ? AArch64::STZ2GPostIndex : AArch64::ST2GPostIndex;
716
717 unsigned Size = MI.getOperand(2).getImm();
718 assert(Size > 0 && Size % 16 == 0);
719 if (Size % (16 * 2) != 0) {
720 BuildMI(MBB, MBBI, DL, TII->get(OpCode1), AddressReg)
721 .addReg(AddressReg)
722 .addReg(AddressReg)
723 .addImm(1);
724 Size -= 16;
725 }
727 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVi64imm), SizeReg)
728 .addImm(Size);
729 expandMOVImm(MBB, I, 64);
730
731 auto LoopBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
732 auto DoneBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
733
734 MF->insert(++MBB.getIterator(), LoopBB);
735 MF->insert(++LoopBB->getIterator(), DoneBB);
736
737 BuildMI(LoopBB, DL, TII->get(OpCode2))
738 .addDef(AddressReg)
739 .addReg(AddressReg)
740 .addReg(AddressReg)
741 .addImm(2)
743 .setMIFlags(MI.getFlags());
744 BuildMI(LoopBB, DL, TII->get(AArch64::SUBSXri))
745 .addDef(SizeReg)
746 .addReg(SizeReg)
747 .addImm(16 * 2)
748 .addImm(0);
749 BuildMI(LoopBB, DL, TII->get(AArch64::Bcc))
751 .addMBB(LoopBB)
752 .addReg(AArch64::NZCV, RegState::Implicit | RegState::Kill);
753
754 LoopBB->addSuccessor(LoopBB);
755 LoopBB->addSuccessor(DoneBB);
756
757 DoneBB->splice(DoneBB->end(), &MBB, MI, MBB.end());
758 DoneBB->transferSuccessors(&MBB);
759
760 MBB.addSuccessor(LoopBB);
761
762 NextMBBI = MBB.end();
763 MI.eraseFromParent();
764 // Recompute liveness bottom up.
765 LivePhysRegs LiveRegs;
766 computeAndAddLiveIns(LiveRegs, *DoneBB);
767 computeAndAddLiveIns(LiveRegs, *LoopBB);
768 // Do an extra pass in the loop to get the loop carried dependencies right.
769 // FIXME: is this necessary?
770 LoopBB->clearLiveIns();
771 computeAndAddLiveIns(LiveRegs, *LoopBB);
772 DoneBB->clearLiveIns();
773 computeAndAddLiveIns(LiveRegs, *DoneBB);
774
775 return true;
776}
777
778bool AArch64ExpandPseudo::expandSVESpillFill(MachineBasicBlock &MBB,
780 unsigned Opc, unsigned N) {
781 assert((Opc == AArch64::LDR_ZXI || Opc == AArch64::STR_ZXI ||
782 Opc == AArch64::LDR_PXI || Opc == AArch64::STR_PXI) &&
783 "Unexpected opcode");
784 unsigned RState = (Opc == AArch64::LDR_ZXI || Opc == AArch64::LDR_PXI)
786 : 0;
787 unsigned sub0 = (Opc == AArch64::LDR_ZXI || Opc == AArch64::STR_ZXI)
788 ? AArch64::zsub0
789 : AArch64::psub0;
790 const TargetRegisterInfo *TRI =
792 MachineInstr &MI = *MBBI;
793 for (unsigned Offset = 0; Offset < N; ++Offset) {
794 int ImmOffset = MI.getOperand(2).getImm() + Offset;
795 bool Kill = (Offset + 1 == N) ? MI.getOperand(1).isKill() : false;
796 assert(ImmOffset >= -256 && ImmOffset < 256 &&
797 "Immediate spill offset out of range");
798 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc))
799 .addReg(TRI->getSubReg(MI.getOperand(0).getReg(), sub0 + Offset),
800 RState)
801 .addReg(MI.getOperand(1).getReg(), getKillRegState(Kill))
802 .addImm(ImmOffset);
803 }
804 MI.eraseFromParent();
805 return true;
806}
807
808// Create a call with the passed opcode and explicit operands, copying over all
809// the implicit operands from *MBBI, starting at the regmask.
812 const AArch64InstrInfo *TII,
813 unsigned Opcode,
814 ArrayRef<MachineOperand> ExplicitOps,
815 unsigned RegMaskStartIdx) {
816 // Build the MI, with explicit operands first (including the call target).
817 MachineInstr *Call = BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(Opcode))
818 .add(ExplicitOps)
819 .getInstr();
820
821 // Register arguments are added during ISel, but cannot be added as explicit
822 // operands of the branch as it expects to be B <target> which is only one
823 // operand. Instead they are implicit operands used by the branch.
824 while (!MBBI->getOperand(RegMaskStartIdx).isRegMask()) {
825 const MachineOperand &MOP = MBBI->getOperand(RegMaskStartIdx);
826 assert(MOP.isReg() && "can only add register operands");
827 Call->addOperand(MachineOperand::CreateReg(
828 MOP.getReg(), /*Def=*/false, /*Implicit=*/true, /*isKill=*/false,
829 /*isDead=*/false, /*isUndef=*/MOP.isUndef()));
830 RegMaskStartIdx++;
831 }
832 for (const MachineOperand &MO :
833 llvm::drop_begin(MBBI->operands(), RegMaskStartIdx))
834 Call->addOperand(MO);
835
836 return Call;
837}
838
839// Create a call to CallTarget, copying over all the operands from *MBBI,
840// starting at the regmask.
843 const AArch64InstrInfo *TII,
844 MachineOperand &CallTarget,
845 unsigned RegMaskStartIdx) {
846 unsigned Opc = CallTarget.isGlobal() ? AArch64::BL : AArch64::BLR;
847
848 assert((CallTarget.isGlobal() || CallTarget.isReg()) &&
849 "invalid operand for regular call");
850 return createCallWithOps(MBB, MBBI, TII, Opc, CallTarget, RegMaskStartIdx);
851}
852
853bool AArch64ExpandPseudo::expandCALL_RVMARKER(
855 // Expand CALL_RVMARKER pseudo to:
856 // - a branch to the call target, followed by
857 // - the special `mov x29, x29` marker, if necessary, and
858 // - another branch, to the runtime function
859 // Mark the sequence as bundle, to avoid passes moving other code in between.
860 MachineInstr &MI = *MBBI;
861 MachineOperand &RVTarget = MI.getOperand(0);
862 bool DoEmitMarker = MI.getOperand(1).getImm();
863 assert(RVTarget.isGlobal() && "invalid operand for attached call");
864
865 MachineInstr *OriginalCall = nullptr;
866
867 if (MI.getOpcode() == AArch64::BLRA_RVMARKER) {
868 // ptrauth call.
869 const MachineOperand &CallTarget = MI.getOperand(2);
870 const MachineOperand &Key = MI.getOperand(3);
871 const MachineOperand &IntDisc = MI.getOperand(4);
872 const MachineOperand &AddrDisc = MI.getOperand(5);
873
874 assert((Key.getImm() == AArch64PACKey::IA ||
875 Key.getImm() == AArch64PACKey::IB) &&
876 "Invalid auth call key");
877
878 MachineOperand Ops[] = {CallTarget, Key, IntDisc, AddrDisc};
879
880 OriginalCall = createCallWithOps(MBB, MBBI, TII, AArch64::BLRA, Ops,
881 /*RegMaskStartIdx=*/6);
882 } else {
883 assert(MI.getOpcode() == AArch64::BLR_RVMARKER && "unknown rvmarker MI");
884 OriginalCall = createCall(MBB, MBBI, TII, MI.getOperand(2),
885 // Regmask starts after the RV and call targets.
886 /*RegMaskStartIdx=*/3);
887 }
888
889 if (DoEmitMarker)
890 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ORRXrs))
891 .addReg(AArch64::FP, RegState::Define)
892 .addReg(AArch64::XZR)
893 .addReg(AArch64::FP)
894 .addImm(0);
895
896 auto *RVCall = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::BL))
897 .add(RVTarget)
898 .getInstr();
899
900 if (MI.shouldUpdateAdditionalCallInfo())
901 MBB.getParent()->moveAdditionalCallInfo(&MI, OriginalCall);
902
903 MI.eraseFromParent();
904 finalizeBundle(MBB, OriginalCall->getIterator(),
905 std::next(RVCall->getIterator()));
906 return true;
907}
908
909bool AArch64ExpandPseudo::expandCALL_BTI(MachineBasicBlock &MBB,
911 // Expand CALL_BTI pseudo to:
912 // - a branch to the call target
913 // - a BTI instruction
914 // Mark the sequence as a bundle, to avoid passes moving other code in
915 // between.
916 MachineInstr &MI = *MBBI;
917 MachineInstr *Call = createCall(MBB, MBBI, TII, MI.getOperand(0),
918 // Regmask starts after the call target.
919 /*RegMaskStartIdx=*/1);
920
921 Call->setCFIType(*MBB.getParent(), MI.getCFIType());
922
923 MachineInstr *BTI =
924 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::HINT))
925 // BTI J so that setjmp can to BR to this.
926 .addImm(36)
927 .getInstr();
928
929 if (MI.shouldUpdateAdditionalCallInfo())
931
932 MI.eraseFromParent();
933 finalizeBundle(MBB, Call->getIterator(), std::next(BTI->getIterator()));
934 return true;
935}
936
937bool AArch64ExpandPseudo::expandStoreSwiftAsyncContext(
939 Register CtxReg = MBBI->getOperand(0).getReg();
940 Register BaseReg = MBBI->getOperand(1).getReg();
941 int Offset = MBBI->getOperand(2).getImm();
942 DebugLoc DL(MBBI->getDebugLoc());
943 auto &STI = MBB.getParent()->getSubtarget<AArch64Subtarget>();
944
945 if (STI.getTargetTriple().getArchName() != "arm64e") {
946 BuildMI(MBB, MBBI, DL, TII->get(AArch64::STRXui))
947 .addUse(CtxReg)
948 .addUse(BaseReg)
949 .addImm(Offset / 8)
952 return true;
953 }
954
955 // We need to sign the context in an address-discriminated way. 0xc31a is a
956 // fixed random value, chosen as part of the ABI.
957 // add x16, xBase, #Offset
958 // movk x16, #0xc31a, lsl #48
959 // mov x17, x22/xzr
960 // pacdb x17, x16
961 // str x17, [xBase, #Offset]
962 unsigned Opc = Offset >= 0 ? AArch64::ADDXri : AArch64::SUBXri;
963 BuildMI(MBB, MBBI, DL, TII->get(Opc), AArch64::X16)
964 .addUse(BaseReg)
965 .addImm(abs(Offset))
966 .addImm(0)
968 BuildMI(MBB, MBBI, DL, TII->get(AArch64::MOVKXi), AArch64::X16)
969 .addUse(AArch64::X16)
970 .addImm(0xc31a)
971 .addImm(48)
973 // We're not allowed to clobber X22 (and couldn't clobber XZR if we tried), so
974 // move it somewhere before signing.
975 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::X17)
976 .addUse(AArch64::XZR)
977 .addUse(CtxReg)
978 .addImm(0)
980 BuildMI(MBB, MBBI, DL, TII->get(AArch64::PACDB), AArch64::X17)
981 .addUse(AArch64::X17)
982 .addUse(AArch64::X16)
984 BuildMI(MBB, MBBI, DL, TII->get(AArch64::STRXui))
985 .addUse(AArch64::X17)
986 .addUse(BaseReg)
987 .addImm(Offset / 8)
989
991 return true;
992}
993
994static constexpr unsigned ZERO_ALL_ZA_MASK = 0b11111111;
995
996MachineBasicBlock *AArch64ExpandPseudo::expandCommitOrRestoreZASave(
998 MachineInstr &MI = *MBBI;
999 bool IsRestoreZA = MI.getOpcode() == AArch64::RestoreZAPseudo;
1000 assert((MI.getOpcode() == AArch64::RestoreZAPseudo ||
1001 MI.getOpcode() == AArch64::CommitZASavePseudo) &&
1002 "Expected ZA commit or restore");
1003 assert((std::next(MBBI) != MBB.end() ||
1004 MI.getParent()->successors().begin() !=
1005 MI.getParent()->successors().end()) &&
1006 "Unexpected unreachable in block that restores ZA");
1007
1008 // Compare TPIDR2_EL0 value against 0.
1009 DebugLoc DL = MI.getDebugLoc();
1010 MachineInstrBuilder Branch =
1011 BuildMI(MBB, MBBI, DL,
1012 TII->get(IsRestoreZA ? AArch64::CBZX : AArch64::CBNZX))
1013 .add(MI.getOperand(0));
1014
1015 // Split MBB and create two new blocks:
1016 // - MBB now contains all instructions before RestoreZAPseudo.
1017 // - SMBB contains the [Commit|RestoreZA]Pseudo instruction only.
1018 // - EndBB contains all instructions after [Commit|RestoreZA]Pseudo.
1019 MachineInstr &PrevMI = *std::prev(MBBI);
1020 MachineBasicBlock *SMBB = MBB.splitAt(PrevMI, /*UpdateLiveIns*/ true);
1021 MachineBasicBlock *EndBB = std::next(MI.getIterator()) == SMBB->end()
1022 ? *SMBB->successors().begin()
1023 : SMBB->splitAt(MI, /*UpdateLiveIns*/ true);
1024
1025 // Add the SMBB label to the CB[N]Z instruction & create a branch to EndBB.
1026 Branch.addMBB(SMBB);
1027 BuildMI(&MBB, DL, TII->get(AArch64::B))
1028 .addMBB(EndBB);
1029 MBB.addSuccessor(EndBB);
1030
1031 // Replace the pseudo with a call (BL).
1033 BuildMI(*SMBB, SMBB->end(), DL, TII->get(AArch64::BL));
1034 // Copy operands (mainly the regmask) from the pseudo.
1035 for (unsigned I = 2; I < MI.getNumOperands(); ++I)
1036 MIB.add(MI.getOperand(I));
1037
1038 if (IsRestoreZA) {
1039 // Mark the TPIDR2 block pointer (X0) as an implicit use.
1040 MIB.addReg(MI.getOperand(1).getReg(), RegState::Implicit);
1041 } else /*CommitZA*/ {
1042 [[maybe_unused]] auto *TRI =
1044 // Clear TPIDR2_EL0.
1045 BuildMI(*SMBB, SMBB->end(), DL, TII->get(AArch64::MSR))
1046 .addImm(AArch64SysReg::TPIDR2_EL0)
1047 .addReg(AArch64::XZR);
1048 bool ZeroZA = MI.getOperand(1).getImm() != 0;
1049 if (ZeroZA) {
1050 assert(MI.definesRegister(AArch64::ZAB0, TRI) && "should define ZA!");
1051 BuildMI(*SMBB, SMBB->end(), DL, TII->get(AArch64::ZERO_M))
1053 .addDef(AArch64::ZAB0, RegState::ImplicitDefine);
1054 }
1055 }
1056
1057 BuildMI(SMBB, DL, TII->get(AArch64::B)).addMBB(EndBB);
1058 MI.eraseFromParent();
1059 return EndBB;
1060}
1061
1063AArch64ExpandPseudo::expandCondSMToggle(MachineBasicBlock &MBB,
1065 MachineInstr &MI = *MBBI;
1066 // In the case of a smstart/smstop before a unreachable, just remove the pseudo.
1067 // Exception handling code generated by Clang may introduce unreachables and it
1068 // seems unnecessary to restore pstate.sm when that happens. Note that it is
1069 // not just an optimisation, the code below expects a successor instruction/block
1070 // in order to split the block at MBBI.
1071 if (std::next(MBBI) == MBB.end() &&
1072 MI.getParent()->successors().begin() ==
1073 MI.getParent()->successors().end()) {
1074 MI.eraseFromParent();
1075 return &MBB;
1076 }
1077
1078 // Expand the pseudo into smstart or smstop instruction. The pseudo has the
1079 // following operands:
1080 //
1081 // MSRpstatePseudo <za|sm|both>, <0|1>, condition[, pstate.sm], <regmask>
1082 //
1083 // The pseudo is expanded into a conditional smstart/smstop, with a
1084 // check if pstate.sm (register) equals the expected value, and if not,
1085 // invokes the smstart/smstop.
1086 //
1087 // As an example, the following block contains a normal call from a
1088 // streaming-compatible function:
1089 //
1090 // OrigBB:
1091 // MSRpstatePseudo 3, 0, IfCallerIsStreaming, %0, <regmask> <- Cond SMSTOP
1092 // bl @normal_callee
1093 // MSRpstatePseudo 3, 1, IfCallerIsStreaming, %0, <regmask> <- Cond SMSTART
1094 //
1095 // ...which will be transformed into:
1096 //
1097 // OrigBB:
1098 // TBNZx %0:gpr64, 0, SMBB
1099 // b EndBB
1100 //
1101 // SMBB:
1102 // MSRpstatesvcrImm1 3, 0, <regmask> <- SMSTOP
1103 //
1104 // EndBB:
1105 // bl @normal_callee
1106 // MSRcond_pstatesvcrImm1 3, 1, <regmask> <- SMSTART
1107 //
1108 DebugLoc DL = MI.getDebugLoc();
1109
1110 // Create the conditional branch based on the third operand of the
1111 // instruction, which tells us if we are wrapping a normal or streaming
1112 // function.
1113 // We test the live value of pstate.sm and toggle pstate.sm if this is not the
1114 // expected value for the callee (0 for a normal callee and 1 for a streaming
1115 // callee).
1116 unsigned Opc;
1117 switch (MI.getOperand(2).getImm()) {
1118 case AArch64SME::Always:
1119 llvm_unreachable("Should have matched to instruction directly");
1121 Opc = AArch64::TBNZW;
1122 break;
1124 Opc = AArch64::TBZW;
1125 break;
1126 }
1127 auto PStateSM = MI.getOperand(3).getReg();
1129 unsigned SMReg32 = TRI->getSubReg(PStateSM, AArch64::sub_32);
1131 BuildMI(MBB, MBBI, DL, TII->get(Opc)).addReg(SMReg32).addImm(0);
1132
1133 // Split MBB and create two new blocks:
1134 // - MBB now contains all instructions before MSRcond_pstatesvcrImm1.
1135 // - SMBB contains the MSRcond_pstatesvcrImm1 instruction only.
1136 // - EndBB contains all instructions after MSRcond_pstatesvcrImm1.
1137 MachineInstr &PrevMI = *std::prev(MBBI);
1138 MachineBasicBlock *SMBB = MBB.splitAt(PrevMI, /*UpdateLiveIns*/ true);
1139 MachineBasicBlock *EndBB = std::next(MI.getIterator()) == SMBB->end()
1140 ? *SMBB->successors().begin()
1141 : SMBB->splitAt(MI, /*UpdateLiveIns*/ true);
1142
1143 // Add the SMBB label to the TB[N]Z instruction & create a branch to EndBB.
1144 Tbx.addMBB(SMBB);
1145 BuildMI(&MBB, DL, TII->get(AArch64::B))
1146 .addMBB(EndBB);
1147 MBB.addSuccessor(EndBB);
1148
1149 // Create the SMSTART/SMSTOP (MSRpstatesvcrImm1) instruction in SMBB.
1150 MachineInstrBuilder MIB = BuildMI(*SMBB, SMBB->begin(), MI.getDebugLoc(),
1151 TII->get(AArch64::MSRpstatesvcrImm1));
1152 // Copy all but the second and third operands of MSRcond_pstatesvcrImm1 (as
1153 // these contain the CopyFromReg for the first argument and the flag to
1154 // indicate whether the callee is streaming or normal).
1155 MIB.add(MI.getOperand(0));
1156 MIB.add(MI.getOperand(1));
1157 for (unsigned i = 4; i < MI.getNumOperands(); ++i)
1158 MIB.add(MI.getOperand(i));
1159
1160 BuildMI(SMBB, DL, TII->get(AArch64::B)).addMBB(EndBB);
1161
1162 MI.eraseFromParent();
1163 return EndBB;
1164}
1165
1166bool AArch64ExpandPseudo::expandMultiVecPseudo(
1168 TargetRegisterClass ContiguousClass, TargetRegisterClass StridedClass,
1169 unsigned ContiguousOp, unsigned StridedOpc) {
1170 MachineInstr &MI = *MBBI;
1171 Register Tuple = MI.getOperand(0).getReg();
1172
1173 auto ContiguousRange = ContiguousClass.getRegisters();
1174 auto StridedRange = StridedClass.getRegisters();
1175 unsigned Opc;
1176 if (llvm::is_contained(ContiguousRange, Tuple.asMCReg())) {
1177 Opc = ContiguousOp;
1178 } else if (llvm::is_contained(StridedRange, Tuple.asMCReg())) {
1179 Opc = StridedOpc;
1180 } else
1181 llvm_unreachable("Cannot expand Multi-Vector pseudo");
1182
1183 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(Opc))
1184 .add(MI.getOperand(0))
1185 .add(MI.getOperand(1))
1186 .add(MI.getOperand(2))
1187 .add(MI.getOperand(3));
1188 transferImpOps(MI, MIB, MIB);
1189 MI.eraseFromParent();
1190 return true;
1191}
1192
1193bool AArch64ExpandPseudo::expandFormTuplePseudo(
1195 MachineBasicBlock::iterator &NextMBBI, unsigned Size) {
1196 assert((Size == 2 || Size == 4) && "Invalid Tuple Size");
1197 MachineInstr &MI = *MBBI;
1198 Register ReturnTuple = MI.getOperand(0).getReg();
1199
1200 const TargetRegisterInfo *TRI =
1202 for (unsigned I = 0; I < Size; ++I) {
1203 Register FormTupleOpReg = MI.getOperand(I + 1).getReg();
1204 Register ReturnTupleSubReg =
1205 TRI->getSubReg(ReturnTuple, AArch64::zsub0 + I);
1206 // Add copies to ensure the subregisters remain in the correct order
1207 // for any contigious operation they are used by.
1208 if (FormTupleOpReg != ReturnTupleSubReg)
1209 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ORR_ZZZ))
1210 .addReg(ReturnTupleSubReg, RegState::Define)
1211 .addReg(FormTupleOpReg)
1212 .addReg(FormTupleOpReg);
1213 }
1214
1215 MI.eraseFromParent();
1216 return true;
1217}
1218
1219/// If MBBI references a pseudo instruction that should be expanded here,
1220/// do the expansion and return true. Otherwise return false.
1221bool AArch64ExpandPseudo::expandMI(MachineBasicBlock &MBB,
1223 MachineBasicBlock::iterator &NextMBBI) {
1224 MachineInstr &MI = *MBBI;
1225 unsigned Opcode = MI.getOpcode();
1226
1227 // Check if we can expand the destructive op
1228 int OrigInstr = AArch64::getSVEPseudoMap(MI.getOpcode());
1229 if (OrigInstr != -1) {
1230 auto &Orig = TII->get(OrigInstr);
1231 if ((Orig.TSFlags & AArch64::DestructiveInstTypeMask) !=
1233 return expand_DestructiveOp(MI, MBB, MBBI);
1234 }
1235 }
1236
1237 switch (Opcode) {
1238 default:
1239 break;
1240
1241 case AArch64::BSPv8i8:
1242 case AArch64::BSPv16i8: {
1243 Register DstReg = MI.getOperand(0).getReg();
1244 if (DstReg == MI.getOperand(3).getReg()) {
1245 // Expand to BIT
1246 auto I = BuildMI(MBB, MBBI, MI.getDebugLoc(),
1247 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BITv8i8
1248 : AArch64::BITv16i8))
1249 .add(MI.getOperand(0))
1250 .add(MI.getOperand(3))
1251 .add(MI.getOperand(2))
1252 .add(MI.getOperand(1));
1253 transferImpOps(MI, I, I);
1254 } else if (DstReg == MI.getOperand(2).getReg()) {
1255 // Expand to BIF
1256 auto I = BuildMI(MBB, MBBI, MI.getDebugLoc(),
1257 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BIFv8i8
1258 : AArch64::BIFv16i8))
1259 .add(MI.getOperand(0))
1260 .add(MI.getOperand(2))
1261 .add(MI.getOperand(3))
1262 .add(MI.getOperand(1));
1263 transferImpOps(MI, I, I);
1264 } else {
1265 // Expand to BSL, use additional move if required
1266 if (DstReg == MI.getOperand(1).getReg()) {
1267 auto I =
1268 BuildMI(MBB, MBBI, MI.getDebugLoc(),
1269 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1270 : AArch64::BSLv16i8))
1271 .add(MI.getOperand(0))
1272 .add(MI.getOperand(1))
1273 .add(MI.getOperand(2))
1274 .add(MI.getOperand(3));
1275 transferImpOps(MI, I, I);
1276 } else {
1277 unsigned RegState =
1278 getRenamableRegState(MI.getOperand(1).isRenamable()) |
1280 MI.getOperand(1).isKill() &&
1281 MI.getOperand(1).getReg() != MI.getOperand(2).getReg() &&
1282 MI.getOperand(1).getReg() != MI.getOperand(3).getReg());
1283 BuildMI(MBB, MBBI, MI.getDebugLoc(),
1284 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::ORRv8i8
1285 : AArch64::ORRv16i8))
1286 .addReg(DstReg,
1288 getRenamableRegState(MI.getOperand(0).isRenamable()))
1289 .addReg(MI.getOperand(1).getReg(), RegState)
1290 .addReg(MI.getOperand(1).getReg(), RegState);
1291 auto I2 =
1292 BuildMI(MBB, MBBI, MI.getDebugLoc(),
1293 TII->get(Opcode == AArch64::BSPv8i8 ? AArch64::BSLv8i8
1294 : AArch64::BSLv16i8))
1295 .add(MI.getOperand(0))
1296 .addReg(DstReg,
1298 MI.getOperand(0).isRenamable()))
1299 .add(MI.getOperand(2))
1300 .add(MI.getOperand(3));
1301 transferImpOps(MI, I2, I2);
1302 }
1303 }
1304 MI.eraseFromParent();
1305 return true;
1306 }
1307
1308 case AArch64::ADDWrr:
1309 case AArch64::SUBWrr:
1310 case AArch64::ADDXrr:
1311 case AArch64::SUBXrr:
1312 case AArch64::ADDSWrr:
1313 case AArch64::SUBSWrr:
1314 case AArch64::ADDSXrr:
1315 case AArch64::SUBSXrr:
1316 case AArch64::ANDWrr:
1317 case AArch64::ANDXrr:
1318 case AArch64::BICWrr:
1319 case AArch64::BICXrr:
1320 case AArch64::ANDSWrr:
1321 case AArch64::ANDSXrr:
1322 case AArch64::BICSWrr:
1323 case AArch64::BICSXrr:
1324 case AArch64::EONWrr:
1325 case AArch64::EONXrr:
1326 case AArch64::EORWrr:
1327 case AArch64::EORXrr:
1328 case AArch64::ORNWrr:
1329 case AArch64::ORNXrr:
1330 case AArch64::ORRWrr:
1331 case AArch64::ORRXrr: {
1332 unsigned Opcode;
1333 switch (MI.getOpcode()) {
1334 default:
1335 return false;
1336 case AArch64::ADDWrr: Opcode = AArch64::ADDWrs; break;
1337 case AArch64::SUBWrr: Opcode = AArch64::SUBWrs; break;
1338 case AArch64::ADDXrr: Opcode = AArch64::ADDXrs; break;
1339 case AArch64::SUBXrr: Opcode = AArch64::SUBXrs; break;
1340 case AArch64::ADDSWrr: Opcode = AArch64::ADDSWrs; break;
1341 case AArch64::SUBSWrr: Opcode = AArch64::SUBSWrs; break;
1342 case AArch64::ADDSXrr: Opcode = AArch64::ADDSXrs; break;
1343 case AArch64::SUBSXrr: Opcode = AArch64::SUBSXrs; break;
1344 case AArch64::ANDWrr: Opcode = AArch64::ANDWrs; break;
1345 case AArch64::ANDXrr: Opcode = AArch64::ANDXrs; break;
1346 case AArch64::BICWrr: Opcode = AArch64::BICWrs; break;
1347 case AArch64::BICXrr: Opcode = AArch64::BICXrs; break;
1348 case AArch64::ANDSWrr: Opcode = AArch64::ANDSWrs; break;
1349 case AArch64::ANDSXrr: Opcode = AArch64::ANDSXrs; break;
1350 case AArch64::BICSWrr: Opcode = AArch64::BICSWrs; break;
1351 case AArch64::BICSXrr: Opcode = AArch64::BICSXrs; break;
1352 case AArch64::EONWrr: Opcode = AArch64::EONWrs; break;
1353 case AArch64::EONXrr: Opcode = AArch64::EONXrs; break;
1354 case AArch64::EORWrr: Opcode = AArch64::EORWrs; break;
1355 case AArch64::EORXrr: Opcode = AArch64::EORXrs; break;
1356 case AArch64::ORNWrr: Opcode = AArch64::ORNWrs; break;
1357 case AArch64::ORNXrr: Opcode = AArch64::ORNXrs; break;
1358 case AArch64::ORRWrr: Opcode = AArch64::ORRWrs; break;
1359 case AArch64::ORRXrr: Opcode = AArch64::ORRXrs; break;
1360 }
1361 MachineFunction &MF = *MBB.getParent();
1362 // Try to create new inst without implicit operands added.
1363 MachineInstr *NewMI = MF.CreateMachineInstr(
1364 TII->get(Opcode), MI.getDebugLoc(), /*NoImplicit=*/true);
1365 MBB.insert(MBBI, NewMI);
1366 MachineInstrBuilder MIB1(MF, NewMI);
1367 MIB1->setPCSections(MF, MI.getPCSections());
1368 MIB1.addReg(MI.getOperand(0).getReg(), RegState::Define)
1369 .add(MI.getOperand(1))
1370 .add(MI.getOperand(2))
1372 transferImpOps(MI, MIB1, MIB1);
1373 if (auto DebugNumber = MI.peekDebugInstrNum())
1374 NewMI->setDebugInstrNum(DebugNumber);
1375 MI.eraseFromParent();
1376 return true;
1377 }
1378
1379 case AArch64::LOADgot: {
1381 Register DstReg = MI.getOperand(0).getReg();
1382 const MachineOperand &MO1 = MI.getOperand(1);
1383 unsigned Flags = MO1.getTargetFlags();
1384
1385 if (MF->getTarget().getCodeModel() == CodeModel::Tiny) {
1386 // Tiny codemodel expand to LDR
1387 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, MI.getDebugLoc(),
1388 TII->get(AArch64::LDRXl), DstReg);
1389
1390 if (MO1.isGlobal()) {
1391 MIB.addGlobalAddress(MO1.getGlobal(), 0, Flags);
1392 } else if (MO1.isSymbol()) {
1393 MIB.addExternalSymbol(MO1.getSymbolName(), Flags);
1394 } else {
1395 assert(MO1.isCPI() &&
1396 "Only expect globals, externalsymbols, or constant pools");
1397 MIB.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(), Flags);
1398 }
1399 } else {
1400 // Small codemodel expand into ADRP + LDR.
1401 MachineFunction &MF = *MI.getParent()->getParent();
1402 DebugLoc DL = MI.getDebugLoc();
1403 MachineInstrBuilder MIB1 =
1404 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg);
1405
1409 unsigned Reg32 = TRI->getSubReg(DstReg, AArch64::sub_32);
1410 unsigned DstFlags = MI.getOperand(0).getTargetFlags();
1411 MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::LDRWui))
1412 .addDef(Reg32)
1413 .addReg(DstReg, RegState::Kill)
1414 .addReg(DstReg, DstFlags | RegState::Implicit);
1415 } else {
1416 Register DstReg = MI.getOperand(0).getReg();
1417 MIB2 = BuildMI(MBB, MBBI, DL, TII->get(AArch64::LDRXui))
1418 .add(MI.getOperand(0))
1419 .addUse(DstReg, RegState::Kill);
1420 }
1421
1422 if (MO1.isGlobal()) {
1423 MIB1.addGlobalAddress(MO1.getGlobal(), 0, Flags | AArch64II::MO_PAGE);
1424 MIB2.addGlobalAddress(MO1.getGlobal(), 0,
1426 } else if (MO1.isSymbol()) {
1428 MIB2.addExternalSymbol(MO1.getSymbolName(), Flags |
1431 } else {
1432 assert(MO1.isCPI() &&
1433 "Only expect globals, externalsymbols, or constant pools");
1434 MIB1.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(),
1435 Flags | AArch64II::MO_PAGE);
1436 MIB2.addConstantPoolIndex(MO1.getIndex(), MO1.getOffset(),
1437 Flags | AArch64II::MO_PAGEOFF |
1439 }
1440
1441 // If the LOADgot instruction has a debug-instr-number, annotate the
1442 // LDRWui instruction that it is expanded to with the same
1443 // debug-instr-number to preserve debug information.
1444 if (MI.peekDebugInstrNum() != 0)
1445 MIB2->setDebugInstrNum(MI.peekDebugInstrNum());
1446 transferImpOps(MI, MIB1, MIB2);
1447 }
1448 MI.eraseFromParent();
1449 return true;
1450 }
1451 case AArch64::MOVaddrBA: {
1452 MachineFunction &MF = *MI.getParent()->getParent();
1454 // blockaddress expressions have to come from a constant pool because the
1455 // largest addend (and hence offset within a function) allowed for ADRP is
1456 // only 8MB.
1457 const BlockAddress *BA = MI.getOperand(1).getBlockAddress();
1458 assert(MI.getOperand(1).getOffset() == 0 && "unexpected offset");
1459
1461 unsigned CPIdx = MCP->getConstantPoolIndex(BA, Align(8));
1462
1463 Register DstReg = MI.getOperand(0).getReg();
1464 auto MIB1 =
1465 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg)
1467 auto MIB2 = BuildMI(MBB, MBBI, MI.getDebugLoc(),
1468 TII->get(AArch64::LDRXui), DstReg)
1469 .addUse(DstReg)
1472 transferImpOps(MI, MIB1, MIB2);
1473 MI.eraseFromParent();
1474 return true;
1475 }
1476 }
1477 [[fallthrough]];
1478 case AArch64::MOVaddr:
1479 case AArch64::MOVaddrJT:
1480 case AArch64::MOVaddrCP:
1481 case AArch64::MOVaddrTLS:
1482 case AArch64::MOVaddrEXT: {
1483 // Expand into ADRP + ADD.
1484 Register DstReg = MI.getOperand(0).getReg();
1485 assert(DstReg != AArch64::XZR);
1486 MachineInstrBuilder MIB1 =
1487 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADRP), DstReg)
1488 .add(MI.getOperand(1));
1489
1490 if (MI.getOperand(1).getTargetFlags() & AArch64II::MO_TAGGED) {
1491 // MO_TAGGED on the page indicates a tagged address. Set the tag now.
1492 // We do so by creating a MOVK that sets bits 48-63 of the register to
1493 // (global address + 0x100000000 - PC) >> 48. This assumes that we're in
1494 // the small code model so we can assume a binary size of <= 4GB, which
1495 // makes the untagged PC relative offset positive. The binary must also be
1496 // loaded into address range [0, 2^48). Both of these properties need to
1497 // be ensured at runtime when using tagged addresses.
1498 auto Tag = MI.getOperand(1);
1499 Tag.setTargetFlags(AArch64II::MO_PREL | AArch64II::MO_G3);
1500 Tag.setOffset(0x100000000);
1501 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MOVKXi), DstReg)
1502 .addReg(DstReg)
1503 .add(Tag)
1504 .addImm(48);
1505 }
1506
1507 MachineInstrBuilder MIB2 =
1508 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADDXri))
1509 .add(MI.getOperand(0))
1510 .addReg(DstReg)
1511 .add(MI.getOperand(2))
1512 .addImm(0);
1513
1514 transferImpOps(MI, MIB1, MIB2);
1515 MI.eraseFromParent();
1516 return true;
1517 }
1518 case AArch64::ADDlowTLS:
1519 // Produce a plain ADD
1520 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::ADDXri))
1521 .add(MI.getOperand(0))
1522 .add(MI.getOperand(1))
1523 .add(MI.getOperand(2))
1524 .addImm(0);
1525 MI.eraseFromParent();
1526 return true;
1527
1528 case AArch64::MOVbaseTLS: {
1529 Register DstReg = MI.getOperand(0).getReg();
1530 auto SysReg = AArch64SysReg::TPIDR_EL0;
1532 if (MF->getSubtarget<AArch64Subtarget>().useEL3ForTP())
1533 SysReg = AArch64SysReg::TPIDR_EL3;
1534 else if (MF->getSubtarget<AArch64Subtarget>().useEL2ForTP())
1535 SysReg = AArch64SysReg::TPIDR_EL2;
1536 else if (MF->getSubtarget<AArch64Subtarget>().useEL1ForTP())
1537 SysReg = AArch64SysReg::TPIDR_EL1;
1538 else if (MF->getSubtarget<AArch64Subtarget>().useROEL0ForTP())
1539 SysReg = AArch64SysReg::TPIDRRO_EL0;
1540 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::MRS), DstReg)
1541 .addImm(SysReg);
1542 MI.eraseFromParent();
1543 return true;
1544 }
1545
1546 case AArch64::MOVi32imm:
1547 return expandMOVImm(MBB, MBBI, 32);
1548 case AArch64::MOVi64imm:
1549 return expandMOVImm(MBB, MBBI, 64);
1550 case AArch64::RET_ReallyLR: {
1551 // Hiding the LR use with RET_ReallyLR may lead to extra kills in the
1552 // function and missing live-ins. We are fine in practice because callee
1553 // saved register handling ensures the register value is restored before
1554 // RET, but we need the undef flag here to appease the MachineVerifier
1555 // liveness checks.
1557 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::RET))
1558 .addReg(AArch64::LR, RegState::Undef);
1559 transferImpOps(MI, MIB, MIB);
1560 MI.eraseFromParent();
1561 return true;
1562 }
1563 case AArch64::CMP_SWAP_8:
1564 return expandCMP_SWAP(MBB, MBBI, AArch64::LDAXRB, AArch64::STLXRB,
1565 AArch64::SUBSWrx,
1567 AArch64::WZR, NextMBBI);
1568 case AArch64::CMP_SWAP_16:
1569 return expandCMP_SWAP(MBB, MBBI, AArch64::LDAXRH, AArch64::STLXRH,
1570 AArch64::SUBSWrx,
1572 AArch64::WZR, NextMBBI);
1573 case AArch64::CMP_SWAP_32:
1574 return expandCMP_SWAP(MBB, MBBI, AArch64::LDAXRW, AArch64::STLXRW,
1575 AArch64::SUBSWrs,
1577 AArch64::WZR, NextMBBI);
1578 case AArch64::CMP_SWAP_64:
1579 return expandCMP_SWAP(MBB, MBBI,
1580 AArch64::LDAXRX, AArch64::STLXRX, AArch64::SUBSXrs,
1582 AArch64::XZR, NextMBBI);
1583 case AArch64::CMP_SWAP_128:
1584 case AArch64::CMP_SWAP_128_RELEASE:
1585 case AArch64::CMP_SWAP_128_ACQUIRE:
1586 case AArch64::CMP_SWAP_128_MONOTONIC:
1587 return expandCMP_SWAP_128(MBB, MBBI, NextMBBI);
1588
1589 case AArch64::AESMCrrTied:
1590 case AArch64::AESIMCrrTied: {
1592 BuildMI(MBB, MBBI, MI.getDebugLoc(),
1593 TII->get(Opcode == AArch64::AESMCrrTied ? AArch64::AESMCrr :
1594 AArch64::AESIMCrr))
1595 .add(MI.getOperand(0))
1596 .add(MI.getOperand(1));
1597 transferImpOps(MI, MIB, MIB);
1598 MI.eraseFromParent();
1599 return true;
1600 }
1601 case AArch64::IRGstack: {
1602 MachineFunction &MF = *MBB.getParent();
1604 const AArch64FrameLowering *TFI =
1605 MF.getSubtarget<AArch64Subtarget>().getFrameLowering();
1606
1607 // IRG does not allow immediate offset. getTaggedBasePointerOffset should
1608 // almost always point to SP-after-prologue; if not, emit a longer
1609 // instruction sequence.
1610 int BaseOffset = -AFI->getTaggedBasePointerOffset();
1611 Register FrameReg;
1612 StackOffset FrameRegOffset = TFI->resolveFrameOffsetReference(
1613 MF, BaseOffset, false /*isFixed*/, false /*isSVE*/, FrameReg,
1614 /*PreferFP=*/false,
1615 /*ForSimm=*/true);
1616 Register SrcReg = FrameReg;
1617 if (FrameRegOffset) {
1618 // Use output register as temporary.
1619 SrcReg = MI.getOperand(0).getReg();
1620 emitFrameOffset(MBB, &MI, MI.getDebugLoc(), SrcReg, FrameReg,
1621 FrameRegOffset, TII);
1622 }
1623 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(AArch64::IRG))
1624 .add(MI.getOperand(0))
1625 .addUse(SrcReg)
1626 .add(MI.getOperand(2));
1627 MI.eraseFromParent();
1628 return true;
1629 }
1630 case AArch64::TAGPstack: {
1631 int64_t Offset = MI.getOperand(2).getImm();
1632 BuildMI(MBB, MBBI, MI.getDebugLoc(),
1633 TII->get(Offset >= 0 ? AArch64::ADDG : AArch64::SUBG))
1634 .add(MI.getOperand(0))
1635 .add(MI.getOperand(1))
1636 .addImm(std::abs(Offset))
1637 .add(MI.getOperand(4));
1638 MI.eraseFromParent();
1639 return true;
1640 }
1641 case AArch64::STGloop_wback:
1642 case AArch64::STZGloop_wback:
1643 return expandSetTagLoop(MBB, MBBI, NextMBBI);
1644 case AArch64::STGloop:
1645 case AArch64::STZGloop:
1647 "Non-writeback variants of STGloop / STZGloop should not "
1648 "survive past PrologEpilogInserter.");
1649 case AArch64::STR_ZZZZXI:
1650 case AArch64::STR_ZZZZXI_STRIDED_CONTIGUOUS:
1651 return expandSVESpillFill(MBB, MBBI, AArch64::STR_ZXI, 4);
1652 case AArch64::STR_ZZZXI:
1653 return expandSVESpillFill(MBB, MBBI, AArch64::STR_ZXI, 3);
1654 case AArch64::STR_ZZXI:
1655 case AArch64::STR_ZZXI_STRIDED_CONTIGUOUS:
1656 return expandSVESpillFill(MBB, MBBI, AArch64::STR_ZXI, 2);
1657 case AArch64::STR_PPXI:
1658 return expandSVESpillFill(MBB, MBBI, AArch64::STR_PXI, 2);
1659 case AArch64::LDR_ZZZZXI:
1660 case AArch64::LDR_ZZZZXI_STRIDED_CONTIGUOUS:
1661 return expandSVESpillFill(MBB, MBBI, AArch64::LDR_ZXI, 4);
1662 case AArch64::LDR_ZZZXI:
1663 return expandSVESpillFill(MBB, MBBI, AArch64::LDR_ZXI, 3);
1664 case AArch64::LDR_ZZXI:
1665 case AArch64::LDR_ZZXI_STRIDED_CONTIGUOUS:
1666 return expandSVESpillFill(MBB, MBBI, AArch64::LDR_ZXI, 2);
1667 case AArch64::LDR_PPXI:
1668 return expandSVESpillFill(MBB, MBBI, AArch64::LDR_PXI, 2);
1669 case AArch64::BLR_RVMARKER:
1670 case AArch64::BLRA_RVMARKER:
1671 return expandCALL_RVMARKER(MBB, MBBI);
1672 case AArch64::BLR_BTI:
1673 return expandCALL_BTI(MBB, MBBI);
1674 case AArch64::StoreSwiftAsyncContext:
1675 return expandStoreSwiftAsyncContext(MBB, MBBI);
1676 case AArch64::CommitZASavePseudo:
1677 case AArch64::RestoreZAPseudo: {
1678 auto *NewMBB = expandCommitOrRestoreZASave(MBB, MBBI);
1679 if (NewMBB != &MBB)
1680 NextMBBI = MBB.end(); // The NextMBBI iterator is invalidated.
1681 return true;
1682 }
1683 case AArch64::MSRpstatePseudo: {
1684 auto *NewMBB = expandCondSMToggle(MBB, MBBI);
1685 if (NewMBB != &MBB)
1686 NextMBBI = MBB.end(); // The NextMBBI iterator is invalidated.
1687 return true;
1688 }
1689 case AArch64::InOutZAUsePseudo:
1690 case AArch64::RequiresZASavePseudo:
1691 case AArch64::COALESCER_BARRIER_FPR16:
1692 case AArch64::COALESCER_BARRIER_FPR32:
1693 case AArch64::COALESCER_BARRIER_FPR64:
1694 case AArch64::COALESCER_BARRIER_FPR128:
1695 MI.eraseFromParent();
1696 return true;
1697 case AArch64::LD1B_2Z_IMM_PSEUDO:
1698 return expandMultiVecPseudo(
1699 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1700 AArch64::LD1B_2Z_IMM, AArch64::LD1B_2Z_STRIDED_IMM);
1701 case AArch64::LD1H_2Z_IMM_PSEUDO:
1702 return expandMultiVecPseudo(
1703 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1704 AArch64::LD1H_2Z_IMM, AArch64::LD1H_2Z_STRIDED_IMM);
1705 case AArch64::LD1W_2Z_IMM_PSEUDO:
1706 return expandMultiVecPseudo(
1707 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1708 AArch64::LD1W_2Z_IMM, AArch64::LD1W_2Z_STRIDED_IMM);
1709 case AArch64::LD1D_2Z_IMM_PSEUDO:
1710 return expandMultiVecPseudo(
1711 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1712 AArch64::LD1D_2Z_IMM, AArch64::LD1D_2Z_STRIDED_IMM);
1713 case AArch64::LDNT1B_2Z_IMM_PSEUDO:
1714 return expandMultiVecPseudo(
1715 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1716 AArch64::LDNT1B_2Z_IMM, AArch64::LDNT1B_2Z_STRIDED_IMM);
1717 case AArch64::LDNT1H_2Z_IMM_PSEUDO:
1718 return expandMultiVecPseudo(
1719 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1720 AArch64::LDNT1H_2Z_IMM, AArch64::LDNT1H_2Z_STRIDED_IMM);
1721 case AArch64::LDNT1W_2Z_IMM_PSEUDO:
1722 return expandMultiVecPseudo(
1723 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1724 AArch64::LDNT1W_2Z_IMM, AArch64::LDNT1W_2Z_STRIDED_IMM);
1725 case AArch64::LDNT1D_2Z_IMM_PSEUDO:
1726 return expandMultiVecPseudo(
1727 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1728 AArch64::LDNT1D_2Z_IMM, AArch64::LDNT1D_2Z_STRIDED_IMM);
1729 case AArch64::LD1B_2Z_PSEUDO:
1730 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR2RegClass,
1731 AArch64::ZPR2StridedRegClass, AArch64::LD1B_2Z,
1732 AArch64::LD1B_2Z_STRIDED);
1733 case AArch64::LD1H_2Z_PSEUDO:
1734 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR2RegClass,
1735 AArch64::ZPR2StridedRegClass, AArch64::LD1H_2Z,
1736 AArch64::LD1H_2Z_STRIDED);
1737 case AArch64::LD1W_2Z_PSEUDO:
1738 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR2RegClass,
1739 AArch64::ZPR2StridedRegClass, AArch64::LD1W_2Z,
1740 AArch64::LD1W_2Z_STRIDED);
1741 case AArch64::LD1D_2Z_PSEUDO:
1742 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR2RegClass,
1743 AArch64::ZPR2StridedRegClass, AArch64::LD1D_2Z,
1744 AArch64::LD1D_2Z_STRIDED);
1745 case AArch64::LDNT1B_2Z_PSEUDO:
1746 return expandMultiVecPseudo(
1747 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1748 AArch64::LDNT1B_2Z, AArch64::LDNT1B_2Z_STRIDED);
1749 case AArch64::LDNT1H_2Z_PSEUDO:
1750 return expandMultiVecPseudo(
1751 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1752 AArch64::LDNT1H_2Z, AArch64::LDNT1H_2Z_STRIDED);
1753 case AArch64::LDNT1W_2Z_PSEUDO:
1754 return expandMultiVecPseudo(
1755 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1756 AArch64::LDNT1W_2Z, AArch64::LDNT1W_2Z_STRIDED);
1757 case AArch64::LDNT1D_2Z_PSEUDO:
1758 return expandMultiVecPseudo(
1759 MBB, MBBI, AArch64::ZPR2RegClass, AArch64::ZPR2StridedRegClass,
1760 AArch64::LDNT1D_2Z, AArch64::LDNT1D_2Z_STRIDED);
1761 case AArch64::LD1B_4Z_IMM_PSEUDO:
1762 return expandMultiVecPseudo(
1763 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1764 AArch64::LD1B_4Z_IMM, AArch64::LD1B_4Z_STRIDED_IMM);
1765 case AArch64::LD1H_4Z_IMM_PSEUDO:
1766 return expandMultiVecPseudo(
1767 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1768 AArch64::LD1H_4Z_IMM, AArch64::LD1H_4Z_STRIDED_IMM);
1769 case AArch64::LD1W_4Z_IMM_PSEUDO:
1770 return expandMultiVecPseudo(
1771 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1772 AArch64::LD1W_4Z_IMM, AArch64::LD1W_4Z_STRIDED_IMM);
1773 case AArch64::LD1D_4Z_IMM_PSEUDO:
1774 return expandMultiVecPseudo(
1775 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1776 AArch64::LD1D_4Z_IMM, AArch64::LD1D_4Z_STRIDED_IMM);
1777 case AArch64::LDNT1B_4Z_IMM_PSEUDO:
1778 return expandMultiVecPseudo(
1779 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1780 AArch64::LDNT1B_4Z_IMM, AArch64::LDNT1B_4Z_STRIDED_IMM);
1781 case AArch64::LDNT1H_4Z_IMM_PSEUDO:
1782 return expandMultiVecPseudo(
1783 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1784 AArch64::LDNT1H_4Z_IMM, AArch64::LDNT1H_4Z_STRIDED_IMM);
1785 case AArch64::LDNT1W_4Z_IMM_PSEUDO:
1786 return expandMultiVecPseudo(
1787 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1788 AArch64::LDNT1W_4Z_IMM, AArch64::LDNT1W_4Z_STRIDED_IMM);
1789 case AArch64::LDNT1D_4Z_IMM_PSEUDO:
1790 return expandMultiVecPseudo(
1791 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1792 AArch64::LDNT1D_4Z_IMM, AArch64::LDNT1D_4Z_STRIDED_IMM);
1793 case AArch64::LD1B_4Z_PSEUDO:
1794 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR4RegClass,
1795 AArch64::ZPR4StridedRegClass, AArch64::LD1B_4Z,
1796 AArch64::LD1B_4Z_STRIDED);
1797 case AArch64::LD1H_4Z_PSEUDO:
1798 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR4RegClass,
1799 AArch64::ZPR4StridedRegClass, AArch64::LD1H_4Z,
1800 AArch64::LD1H_4Z_STRIDED);
1801 case AArch64::LD1W_4Z_PSEUDO:
1802 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR4RegClass,
1803 AArch64::ZPR4StridedRegClass, AArch64::LD1W_4Z,
1804 AArch64::LD1W_4Z_STRIDED);
1805 case AArch64::LD1D_4Z_PSEUDO:
1806 return expandMultiVecPseudo(MBB, MBBI, AArch64::ZPR4RegClass,
1807 AArch64::ZPR4StridedRegClass, AArch64::LD1D_4Z,
1808 AArch64::LD1D_4Z_STRIDED);
1809 case AArch64::LDNT1B_4Z_PSEUDO:
1810 return expandMultiVecPseudo(
1811 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1812 AArch64::LDNT1B_4Z, AArch64::LDNT1B_4Z_STRIDED);
1813 case AArch64::LDNT1H_4Z_PSEUDO:
1814 return expandMultiVecPseudo(
1815 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1816 AArch64::LDNT1H_4Z, AArch64::LDNT1H_4Z_STRIDED);
1817 case AArch64::LDNT1W_4Z_PSEUDO:
1818 return expandMultiVecPseudo(
1819 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1820 AArch64::LDNT1W_4Z, AArch64::LDNT1W_4Z_STRIDED);
1821 case AArch64::LDNT1D_4Z_PSEUDO:
1822 return expandMultiVecPseudo(
1823 MBB, MBBI, AArch64::ZPR4RegClass, AArch64::ZPR4StridedRegClass,
1824 AArch64::LDNT1D_4Z, AArch64::LDNT1D_4Z_STRIDED);
1825 case AArch64::FORM_TRANSPOSED_REG_TUPLE_X2_PSEUDO:
1826 return expandFormTuplePseudo(MBB, MBBI, NextMBBI, 2);
1827 case AArch64::FORM_TRANSPOSED_REG_TUPLE_X4_PSEUDO:
1828 return expandFormTuplePseudo(MBB, MBBI, NextMBBI, 4);
1829 }
1830 return false;
1831}
1832
1833/// Iterate over the instructions in basic block MBB and expand any
1834/// pseudo instructions. Return true if anything was modified.
1835bool AArch64ExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
1836 bool Modified = false;
1837
1839 while (MBBI != E) {
1840 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
1841 Modified |= expandMI(MBB, MBBI, NMBBI);
1842 MBBI = NMBBI;
1843 }
1844
1845 return Modified;
1846}
1847
1848bool AArch64ExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
1849 TII = static_cast<const AArch64InstrInfo *>(MF.getSubtarget().getInstrInfo());
1850
1851 bool Modified = false;
1852 for (auto &MBB : MF)
1853 Modified |= expandMBB(MBB);
1854 return Modified;
1855}
1856
1857/// Returns an instance of the pseudo instruction expansion pass.
1859 return new AArch64ExpandPseudo();
1860}
#define AARCH64_EXPAND_PSEUDO_NAME
MachineInstrBuilder & UseMI
static MachineInstr * createCallWithOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const AArch64InstrInfo *TII, unsigned Opcode, ArrayRef< MachineOperand > ExplicitOps, unsigned RegMaskStartIdx)
static constexpr unsigned ZERO_ALL_ZA_MASK
static MachineInstr * createCall(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const AArch64InstrInfo *TII, MachineOperand &CallTarget, unsigned RegMaskStartIdx)
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
uint64_t Size
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
This file implements the LivePhysRegs utility for tracking liveness of physical registers.
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:56
AArch64FunctionInfo - This class is derived from MachineFunctionInfo and contains private AArch64-spe...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
The address of a basic block.
Definition: Constants.h:899
A debug info location.
Definition: DebugLoc.h:124
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:314
A set of physical registers with utility functions to track liveness when walking backward/forward th...
Definition: LivePhysRegs.h:52
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:199
Set of metadata that should be preserved when using BuildMI().
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
LLVM_ABI MachineBasicBlock * splitAt(MachineInstr &SplitInst, bool UpdateLiveIns=true, LiveIntervals *LIS=nullptr)
Split a basic block into 2 pieces at SplitPoint.
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
The MachineConstantPool class keeps track of constants referenced by a function which must be spilled...
unsigned getConstantPoolIndex(const Constant *C, Align Alignment)
getConstantPoolIndex - Create a new entry in the constant pool or return an existing one.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
void moveAdditionalCallInfo(const MachineInstr *Old, const MachineInstr *New)
Move the call site info from Old to \New call site info.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineInstr * CreateMachineInstr(const MCInstrDesc &MCID, DebugLoc DL, bool NoImplicit=false)
CreateMachineInstr - Allocate a new MachineInstr.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
MachineConstantPool * getConstantPool()
getConstantPool - Return the constant pool object for the current function.
MachineBasicBlock * CreateMachineBasicBlock(const BasicBlock *BB=nullptr, std::optional< UniqueBBID > BBID=std::nullopt)
CreateMachineBasicBlock - Allocate a new MachineBasicBlock.
void insert(iterator MBBI, MachineBasicBlock *MBB)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addExternalSymbol(const char *FnName, unsigned TargetFlags=0) const
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 & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & cloneMemRefs(const MachineInstr &OtherMI) const
const MachineInstrBuilder & addUse(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register use operand.
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
MachineInstr * getInstr() const
If conversion operators fail, use this method to get the MachineInstr explicitly.
const MachineInstrBuilder & addDef(Register RegNo, unsigned Flags=0, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
Definition: MachineInstr.h:72
void setDebugInstrNum(unsigned Num)
Set instruction number of this MachineInstr.
Definition: MachineInstr.h:562
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
unsigned getTargetFlags() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
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)
int64_t getOffset() const
Return the offset from the symbol in this operand.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:85
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
MCRegister asMCReg() const
Utility to check-convert this value to a MCRegister.
Definition: Register.h:102
size_t size() const
Definition: SmallVector.h:79
void push_back(const T &Elt)
Definition: SmallVector.h:414
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
StackOffset holds a fixed and a scalable offset in bytes.
Definition: TypeSize.h:34
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
CodeModel::Model getCodeModel() const
Returns the code model.
ArrayRef< MCPhysReg > getRegisters() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
self_iterator getIterator()
Definition: ilist_node.h:134
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MO_NC
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow.
@ MO_PAGEOFF
MO_PAGEOFF - A symbol operand with this flag represents the offset of that symbol within a 4K page.
@ MO_PREL
MO_PREL - Indicates that the bits of the symbol operand represented by MO_G0 etc are PC relative.
@ MO_PAGE
MO_PAGE - A symbol operand with this flag represents the pc-relative offset of the 4K page containing...
@ 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,...
static unsigned getArithExtendImm(AArch64_AM::ShiftExtendType ET, unsigned Imm)
getArithExtendImm - Encode the extend type and shift amount for an arithmetic instruction: imm: 3-bit...
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 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...
int getSVERevInstr(uint16_t Opcode)
int getSVEPseudoMap(uint16_t Opcode)
int getSVENonRevInstr(uint16_t Opcode)
Key
PAL metadata keys.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Renamable
Register that may be renamed.
@ Define
Register definition.
@ Kill
The last use of a register.
@ Undef
Value of the register doesn't matter.
BaseReg
Stack frame base register. Bit 0 of FREInfo.Info.
Definition: SFrame.h:77
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition: STLExtras.h:338
@ Offset
Definition: DWP.cpp:477
LLVM_ABI void finalizeBundle(MachineBasicBlock &MBB, MachineBasicBlock::instr_iterator FirstMI, MachineBasicBlock::instr_iterator LastMI)
finalizeBundle - Finalize a machine instruction bundle which includes a sequence of instructions star...
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
APFloat abs(APFloat X)
Returns the absolute value of the argument.
Definition: APFloat.h:1563
unsigned getDeadRegState(bool B)
FunctionPass * createAArch64ExpandPseudoPass()
Returns an instance of the pseudo instruction expansion pass.
void emitFrameOffset(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, StackOffset Offset, const TargetInstrInfo *TII, MachineInstr::MIFlag=MachineInstr::NoFlags, bool SetNZCV=false, bool NeedsWinCFI=false, bool *HasWinCFI=nullptr, bool EmitCFAOffset=false, StackOffset InitialOffset={}, unsigned FrameReg=AArch64::SP)
emitFrameOffset - Emit instructions as needed to set DestReg to SrcReg plus Offset.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition: Error.cpp:167
unsigned getKillRegState(bool B)
unsigned getRenamableRegState(bool B)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition: STLExtras.h:1916
void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB)
Convenience function combining computeLiveIns() and addLiveIns().
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
Description of the encoding of one expression Op.