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