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